emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Printing


From: YAMAMOTO Mitsuharu
Subject: Re: Printing
Date: Sun, 19 Apr 2009 19:21:16 +0900
User-agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.8 (Shijō) APEL/10.6 Emacs/22.3 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)

>>>>> On Tue, 07 Apr 2009 18:46:01 +0900, YAMAMOTO Mitsuharu <address@hidden> 
>>>>> said:

>>> I tried making a really preliminary proof-of-concept cairo port. :-)
>>> It's still rough and has several glitches/limitations, but at least
>>> it can generate a "resolution-independent screenshot" PDF as
>>> attached.  Maybe I'll clean up the code this weekend and hopefully
>>> post a patch.

>> Here's the patch for the Emacs 23.0.92 pretest (not the trunk HEAD).

>> * No configure support.  The easiest way would be to compile it with
>>   the GTK+ support that is already linked with cairo libs.  Add
>>   -DUSE_CAIRO to CFLAGS to activate the cairo code.

>> * Currently, texts, rectangles (filling and stroking), and trapezoids
>>  for reliefs are drawn using cairo by hooking the corresponding
>>  drawing routine calls in xterm.c.

This time, I combined the cairo drawing code with GTK+ print dialogs
code, which is actually almost the same as examples in the GTK+
reference.  The added primitives are:

(x-page-setup-dialog): Pop up a page setup dialog.
(x-get-page-setup): Return the value of the current page setup.
  It returns an alist like
  ((orientation . portrait)
   (width . 559.2755905511812) (height . 783.5697637795276)
   (left-margin . 18.0) (right-margin . 18.0)
   (top-margin . 18.0) (bottom-margin . 40.32000000000001))
(x-print-frames-dialog FRAMES): Pop up a print dialog to print the
  current contents of FRAMES.

The last one is intended to be called after some pagination (in Lisp)
that creates a frame per page.  Below is a simple example.

(defun test-print-buffer (buffer-or-name)
  "Paginate and print buffer contents."
  (interactive "bBuffer to export:")
  (with-current-buffer buffer-or-name
    (let* ((buffer (current-buffer))
           (start-pos (point-min))
           (end-pos (point-max))
           (page-setup (if (fboundp 'x-get-page-setup)
                           (x-get-page-setup)
                         '((width . 559.0) (height . 783.0))))
           (width-in-points (cdr (assq 'width page-setup)))
           (height-in-points (cdr (assq 'height page-setup)))
           buffers frames)
      (unwind-protect
          (progn
            (with-selected-frame (selected-frame)
              ;; Paginate and create a frame for each page.
              (while (< start-pos end-pos)
                (let ((inhibit-quit t))
                  (set-buffer
                   (make-indirect-buffer
                    buffer (generate-new-buffer-name (buffer-name buffer)) t))
                  (push (current-buffer) buffers)
                  (setq kill-buffer-hook nil) ;; XXX
                  (select-frame (make-frame
                                 '((internal-border-width . 0)
                                   (vertical-scroll-bars . nil)
                                   (left-fringe . 0) (right-fringe . 0)
                                   (menu-bar-lines . 0) (tool-bar-lines . 0)
                                   (line-spacing . 0)
                                   (minibuffer . nil) (visibility . nil)
                                   (cursor-type . nil)))
                                'norecord)
                  (push (selected-frame) frames))
                (set-frame-size (selected-frame)
                                (floor (/ width-in-points (frame-char-width)))
                                (floor (/ height-in-points 
(frame-char-height))))
                (setq header-line-format nil)
                (setq mode-line-format nil)
                (set-window-start nil start-pos)
                (goto-char (window-end nil t))
                (while (and (< start-pos (point))
                            (not (pos-visible-in-window-p (1- (point)))))
                  (backward-char))
                (narrow-to-region start-pos (point))
                (setq start-pos (point))))
            ;; Print the frames.
            (if (null frames)
                (error "Buffer %s is empty" buffer-or-name)
              (mapc 'make-frame-visible frames)
              (if (fboundp 'x-print-frames-dialog)
                  (x-print-frames-dialog (reverse frames))
                ;; Dummy stub just to reproduce an intermittent error
                ;; in x-print-frames-dialog even without it.
                (dolist (frame frames)
                  (unless (eq (frame-visible-p frame) t)
                    (error "Frames to be printed must be visible.")))
                (redisplay t))))
        ;; Clean up
        (mapc 'delete-frame frames)
        (mapc 'kill-buffer buffers)))))

You can try printing with M-x test-print-buffer RET.  Because the
current cairo drawing routines are hooked onto those in xterm.c in
order to minimize the change, you'll see the actual frames on screen.
Moreover, you might get an incorrect printed result because your
window manager may clip the frames to fit in the screen size.
Nevertheless, I think you can get the basic idea with this sample
code.

                                     YAMAMOTO Mitsuharu
                                address@hidden

Attachment: emacs-23.0.92-cairo.patch.gz
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]