emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r111463: * lisp/doc-view.el: Add supp


From: Stefan Monnier
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r111463: * lisp/doc-view.el: Add support for DjVu.
Date: Wed, 09 Jan 2013 16:24:42 -0500
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 111463
fixes bug: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=13164
author: Elias Pipping <address@hidden>
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Wed 2013-01-09 16:24:42 -0500
message:
  * lisp/doc-view.el: Add support for DjVu.
  (doc-view-djvu->png-converter-function): New config var.
  (doc-view-single-page-converter-function, doc-view--image-type)
  (doc-view--image-file-extension): New vars.
  (doc-view-mode): Initialize them.
  (doc-view-goto-page): Use them.
  (doc-view-mode-p): Add support for ddjvu.
  (doc-view-djvu->png-converter-ddjvu, doc-view-djvu->png-1)
  (doc-view-set-up-single-converter): New funs.
  (doc-view-pdf/ps->png): Extend for djvu.
  (doc-view-document->png): Rename from doc-view-pdf->png.
  (doc-view-convert-current-doc): Handle djvu.
  (doc-view-insert-image, doc-view-display)
  (doc-view-already-converted-p): Don't hardcode png.
  (doc-view-set-doc-type): Recognize djvu docs.
modified:
  lisp/ChangeLog
  lisp/doc-view.el
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-01-09 19:48:42 +0000
+++ b/lisp/ChangeLog    2013-01-09 21:24:42 +0000
@@ -1,5 +1,23 @@
 2013-01-09  Elias Pipping  <address@hidden>
 
+       * doc-view.el: Add support for DjVu (bug#13164).
+       (doc-view-djvu->png-converter-function): New config var.
+       (doc-view-single-page-converter-function, doc-view--image-type)
+       (doc-view--image-file-extension): New vars.
+       (doc-view-mode): Initialize them.
+       (doc-view-goto-page): Use them.
+       (doc-view-mode-p): Add support for ddjvu.
+       (doc-view-djvu->png-converter-ddjvu, doc-view-djvu->png-1)
+       (doc-view-set-up-single-converter): New funs.
+       (doc-view-pdf/ps->png): Extend for djvu.
+       (doc-view-document->png): Rename from doc-view-pdf->png.
+       (doc-view-convert-current-doc): Handle djvu.
+       (doc-view-insert-image, doc-view-display)
+       (doc-view-already-converted-p): Don't hardcode png.
+       (doc-view-set-doc-type): Recognize djvu docs.
+
+2013-01-09  Elias Pipping  <address@hidden>
+
        * doc-view.el: Add support for mupdf converter (bug#13164).
        (doc-view-pdfdraw-program, doc-view-pdf->png-converter-function)
        (doc-view-ps->png-converter-function): New config vars.

=== modified file 'lisp/doc-view.el'
--- a/lisp/doc-view.el  2013-01-09 19:48:42 +0000
+++ b/lisp/doc-view.el  2013-01-09 21:24:42 +0000
@@ -145,7 +145,7 @@
 ;;;; Customization Options
 
 (defgroup doc-view nil
-  "In-buffer viewer for PDF, PostScript and DVI files."
+  "In-buffer viewer for PDF, PostScript, DVI, and DJVU files."
   :link '(function-link doc-view)
   :version "22.2"
   :group 'applications
@@ -174,6 +174,15 @@
           function)
   :version "24.4")
 
+;; FIXME: Get rid of it: there's no choice.
+(defcustom doc-view-djvu->png-converter-function
+  'doc-view-djvu->png-converter-ddjvu
+  "Function to call to convert a DJVU file into a PNG file"
+  :type '(radio (function-item doc-view-djvu->png-converter-ddjvu
+                               :doc "Use ddjvu")
+                function))
+
+;; FIXME: Get rid of it: there's no choice.
 (defcustom doc-view-ps->png-converter-function
   'doc-view-ps->png-converter-ghostscript
   "Function to call to convert a PS file into a PNG file."
@@ -344,6 +353,20 @@
   "The type of document in the current buffer.
 Can be `dvi', `pdf', or `ps'.")
 
+(defvar doc-view-single-page-converter-function nil
+  "Function to call to convert a single page of the document to a bitmap file.
+May operate on the source document or on some intermediate (typically PDF)
+conversion of it.")
+
+(defvar doc-view--image-type nil
+  "The type of image in the current buffer.
+Can be `png' or `tiff'.")
+
+(defvar doc-view--image-file-extension nil
+  ;; FIXME: Replace it with a `format' string, like "page-%d.png".
+  "The file extension of the image type in the current buffer.
+Can be `png' or `tif'.")
+
 ;;;; DocView Keymaps
 
 (defvar doc-view-mode-map
@@ -482,24 +505,26 @@
     ;; We used to find the file name from doc-view-current-files but
     ;; that's not right if the pages are not generated sequentially
     ;; or if the page isn't in doc-view-current-files yet.
-    (let ((file (expand-file-name (format "page-%d.png" page)
-                                  (doc-view-current-cache-dir))))
+    (let ((file (expand-file-name
+                 (format "page-%d.%s" page doc-view--image-file-extension)
+                 (doc-view-current-cache-dir))))
       (doc-view-insert-image file :pointer 'arrow)
       (set-window-hscroll (selected-window) hscroll)
       (when (and (not (file-exists-p file))
                  doc-view-current-converter-processes)
         ;; The PNG file hasn't been generated yet.
-        (doc-view-pdf->png-1 doc-view-buffer-file-name file page
-                             (let ((win (selected-window)))
-                               (lambda ()
-                                 (and (eq (current-buffer) (window-buffer win))
-                                      ;; If we changed page in the mean
-                                      ;; time, don't mess things up.
-                                      (eq (doc-view-current-page win) page)
-                                      ;; Make sure we don't infloop.
-                                      (file-readable-p file)
-                                      (with-selected-window win
-                                                           (doc-view-goto-page 
page))))))))
+        (funcall doc-view-single-page-converter-function
+                doc-view-buffer-file-name file page
+                (let ((win (selected-window)))
+                  (lambda ()
+                    (and (eq (current-buffer) (window-buffer win))
+                         ;; If we changed page in the mean
+                         ;; time, don't mess things up.
+                         (eq (doc-view-current-page win) page)
+                         ;; Make sure we don't infloop.
+                         (file-readable-p file)
+                         (with-selected-window win
+                           (doc-view-goto-page page))))))))
     (overlay-put (doc-view-current-overlay)
                  'help-echo (doc-view-current-info))))
 
@@ -692,6 +717,8 @@
         (and doc-view-unoconv-program
              (executable-find doc-view-unoconv-program)
              (doc-view-mode-p 'pdf)))
+       ((eq type 'djvu)
+        (executable-find "ddjvu"))
        (t ;; unknown image type
         nil))))
 
@@ -863,6 +890,17 @@
 (defalias 'doc-view-ps->png-converter-ghostscript
   'doc-view-pdf->png-converter-ghostscript)
 
+(defun doc-view-djvu->png-converter-ddjvu (resolution djvu png &optional page)
+  `((command . "ddjvu")
+    (arguments . ("-format=tiff"
+                  ;; ddjvu only accepts the range 1-999.
+                 ,(format "-scale=%d" resolution)
+                 ;; -eachpage was only added after djvulibre-3.5.25.3!
+                 ,@(unless page '("-eachpage"))
+                 ,@(if page `(,(format "-page=%d" page)))
+                 ,djvu
+                 ,png))))
+
 (defun doc-view-pdf->png-converter-mupdf (resolution pdf png &optional page)
   `((command . ,doc-view-pdfdraw-program)
     (arguments . (,(concat "-o" png)
@@ -879,13 +917,15 @@
                          callback))
 
 (defun doc-view-pdf/ps->png (pdf-ps png)
+  ;; FIXME: Fix name and docstring to account for djvu&tiff.
   "Convert PDF-PS to PNG asynchronously."
   (let ((invocation
-         (pcase doc-view-doc-type
-           (`pdf (funcall doc-view-pdf->png-converter-function
-                          (round doc-view-resolution) pdf-ps png))
-           (_    (funcall doc-view-ps->png-converter-function
-                          (round doc-view-resolution) pdf-ps png)))))
+         (funcall (pcase doc-view-doc-type
+                    (`pdf doc-view-pdf->png-converter-function)
+                    (`djvu doc-view-djvu->png-converter-function)
+                    (_    doc-view-ps->png-converter-function))
+                  (round doc-view-resolution) pdf-ps png)))
+
     (doc-view-start-process
      "pdf/ps->png" (cdr (assoc 'command invocation))
      (cdr (assoc 'arguments invocation))
@@ -918,9 +958,20 @@
      (cdr (assoc 'arguments invocation))
      callback)))
 
+(defun doc-view-djvu->png-1 (djvu png page callback)
+  "Convert a PAGE of a DJVU file to bitmap asynchronously.
+Call CALLBACK with no arguments when done."
+  (let ((invocation (funcall doc-view-djvu->png-converter-function
+                            (round doc-view-resolution) djvu png page)))
+    (doc-view-start-process
+     "djvu->png" (cdr (assoc 'command invocation))
+     (cdr (assoc 'arguments invocation))
+     callback)))
+
 (declare-function clear-image-cache "image.c" (&optional filter))
 
-(defun doc-view-pdf->png (pdf png pages)
+(defun doc-view-document->png (pdf png pages single-page-converter)
+  ;; FIXME: Fix docstring.
   "Convert a PDF file to PNG asynchronously.
 Start by converting PAGES, and then the rest."
   (if (null pages)
@@ -930,11 +981,11 @@
     ;; a single page anyway, and of the remaining 1%, few cases will have
     ;; consecutive pages, it's not worth the trouble.
     (let ((rest (cdr pages)))
-      (doc-view-pdf->png-1
-       pdf (format png (car pages)) (car pages)
+      (funcall single-page-converter
+              pdf (format png (car pages)) (car pages)
        (lambda ()
          (if rest
-             (doc-view-pdf->png pdf png rest)
+             (doc-view-document->png pdf png rest)
            ;; Yippie, the important pages are done, update the display.
            (clear-image-cache)
            ;; For the windows that have a message (like "Welcome to
@@ -942,8 +993,8 @@
            ;; not sufficient.
            (dolist (win (get-buffer-window-list (current-buffer) nil 'visible))
              (with-selected-window win
-                                  (when (stringp (get-char-property 
(point-min) 'display))
-                                    (doc-view-goto-page 
(doc-view-current-page)))))
+              (when (stringp (get-char-property (point-min) 'display))
+                (doc-view-goto-page (doc-view-current-page)))))
            ;; Convert the rest of the pages.
            (doc-view-pdf/ps->png pdf png)))))))
 
@@ -1013,8 +1064,9 @@
   ;; preserves the horizontal/vertical scroll settings (which are otherwise
   ;; resets during the redisplay).
   (setq doc-view-pending-cache-flush t)
-  (let ((png-file (expand-file-name "page-%d.png"
-                                    (doc-view-current-cache-dir))))
+  (let ((png-file (expand-file-name
+                   (concat "page-%d." doc-view--image-file-extension)
+                   (doc-view-current-cache-dir))))
     (make-directory (doc-view-current-cache-dir) t)
     (pcase doc-view-doc-type
       (`dvi
@@ -1027,11 +1079,12 @@
        ;; ODF files have to be converted to PDF before Ghostscript can
        ;; process it.
        (let ((pdf (doc-view-current-cache-doc-pdf))
-             (opdf (expand-file-name (concat (file-name-base 
doc-view-buffer-file-name)
-                                             ".pdf")
-                                     doc-view-current-cache-dir))
+             (opdf (expand-file-name
+                    (concat (file-name-base doc-view-buffer-file-name)
+                            ".pdf")
+                    doc-view-current-cache-dir))
              (png-file png-file))
-        ;; The unoconv tool only supports a output directory, but no
+        ;; The unoconv tool only supports an output directory, but no
         ;; file name.  It's named like the input file with the
         ;; extension replaced by pdf.
          (doc-view-odf->pdf doc-view-buffer-file-name
@@ -1042,7 +1095,12 @@
       (`pdf
        (let ((pages (doc-view-active-pages)))
          ;; Convert PDF to PNG images starting with the active pages.
-         (doc-view-pdf->png doc-view-buffer-file-name png-file pages)))
+         (doc-view-document->png doc-view-buffer-file-name png-file pages
+                                'doc-view-pdf->png-1)))
+      (`djvu
+       (let ((pages (doc-view-active-pages)))
+        (doc-view-document->png doc-view-buffer-file-name png-file pages
+                                'doc-view-djvu->png-1)))
       (_
        ;; Convert to PNG images.
        (doc-view-pdf/ps->png doc-view-buffer-file-name png-file)))))
@@ -1186,7 +1244,7 @@
         (image (if (and file (file-readable-p file))
                   (if (not (and doc-view-scale-internally
                                  (fboundp 'imagemagick-types)))
-                      (apply 'create-image file 'png nil args)
+                      (apply 'create-image file doc-view--image-type nil args)
                     (unless (member :width args)
                       (setq args `(,@args :width ,doc-view-image-width)))
                     (apply 'create-image file 'imagemagick nil args))))
@@ -1236,13 +1294,17 @@
     (let ((prev-pages doc-view-current-files))
       (setq doc-view-current-files
             (sort (directory-files (doc-view-current-cache-dir) t
-                                   "page-[0-9]+\\.png" t)
+                                   (concat "page-[0-9]+\\."
+                                           doc-view--image-file-extension)
+                                   t)
                   'doc-view-sort))
       (dolist (win (or (get-buffer-window-list buffer nil t)
                       (list t)))
        (let* ((page (doc-view-current-page win))
-              (pagefile (expand-file-name (format "page-%d.png" page)
-                                          (doc-view-current-cache-dir))))
+              (pagefile (expand-file-name
+                          (format "page-%d.%s"
+                                  page doc-view--image-file-extension)
+                          (doc-view-current-cache-dir))))
          (when (or force
                    (and (not (member pagefile prev-pages))
                         (member pagefile doc-view-current-files)))
@@ -1435,12 +1497,13 @@
        ;; the conversion is incomplete.
        (file-readable-p (expand-file-name "resolution.el"
                                           (doc-view-current-cache-dir)))
-       (> (length (directory-files (doc-view-current-cache-dir)
-                                   nil "\\.png\\'"))
+       (> (length (directory-files
+                   (doc-view-current-cache-dir)
+                   nil (concat "\\." doc-view--image-file-extension "\\'")))
           0)))
 
 (defun doc-view-initiate-display ()
-  ;; Switch to image display if possible
+  ;; Switch to image display if possible.
   (if (doc-view-mode-p doc-view-doc-type)
       (progn
        (doc-view-buffer-message)
@@ -1509,6 +1572,8 @@
                         ("pdf" pdf) ("epdf" pdf)
                         ;; PostScript
                         ("ps" ps) ("eps" ps)
+                        ;; DjVu
+                        ("djvu" djvu)
                         ;; OpenDocument formats
                         ("odt" odf) ("ods" odf) ("odp" odf) ("odg" odf)
                         ("odc" odf) ("odi" odf) ("odm" odf) ("ott" odf)
@@ -1523,7 +1588,8 @@
           (cond
            ((looking-at "%!") '(ps))
            ((looking-at "%PDF") '(pdf))
-           ((looking-at "\367\002") '(dvi))))))
+           ((looking-at "\367\002") '(dvi))
+           ((looking-at "AT&TFORM") '(djvu))))))
     (set (make-local-variable 'doc-view-doc-type)
         (car (or (doc-view-intersection name-types content-types)
                  (when (and name-types content-types)
@@ -1532,6 +1598,16 @@
                  name-types content-types
                  (error "Cannot determine the document type"))))))
 
+(defun doc-view-set-up-single-converter ()
+  "Find the right single-page converter for the current document type"
+  (pcase-let ((`(,conv-function ,type ,extension)
+               (pcase doc-view-doc-type
+                 (`djvu (list #'doc-view-djvu->png-1 'tiff "tif"))
+                 (_     (list #'doc-view-pdf->png-1  'png  "png")))))
+    (setq-local doc-view-single-page-converter-function conv-function)
+    (setq-local doc-view--image-type type)
+    (setq-local doc-view--image-file-extension extension)))
+
 ;;;###autoload
 (defun doc-view-mode ()
   "Major mode in DocView buffers.
@@ -1564,6 +1640,7 @@
     ;; Figure out the document type.
     (unless doc-view-doc-type
       (doc-view-set-doc-type))
+    (doc-view-set-up-single-converter)
 
     (doc-view-make-safe-dir doc-view-cache-directory)
     ;; Handle compressed files, remote files, files inside archives


reply via email to

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