diff options
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | lisp/pdf-misc.el | 6 | ||||
| -rw-r--r-- | lisp/pdf-view.el | 163 |
3 files changed, 136 insertions, 35 deletions
@@ -6,6 +6,8 @@ The keys m and ' now set resp. jump to a register corresponging to a position in the PDF. Also '' is handled special: It jumps to the position before the last register-jump. +*** Export parts of a page as an image + * Version 0.60 ** Regexp support You may now search for perl-compatible regular expressions (PCRE) diff --git a/lisp/pdf-misc.el b/lisp/pdf-misc.el index f2b2ad4..b1a2630 100644 --- a/lisp/pdf-misc.el +++ b/lisp/pdf-misc.el @@ -123,8 +123,8 @@ :selected pdf-view-printer-minor-mode :help "Display the PDF as it would be printed."] ["Midnight Mode" (lambda () - (interactive) - (pdf-view-midnight-minor-mode 'toggle)) + (interactive) + (pdf-view-midnight-minor-mode 'toggle)) :style toggle :selected pdf-view-midnight-minor-mode :help "Apply a color-filter appropriate for past midnight reading."]) @@ -146,6 +146,8 @@ (equal last-command-event last-nonmenu-event))] ["Print" pdf-misc-print-document] + ["Create image" pdf-view-extract-region-image + :help "Create an image of the page or the selected region(s)."] "--" ["Revert buffer" pdf-view-revert-buffer :visible (pdf-info-writable-annotations-p)] diff --git a/lisp/pdf-view.el b/lisp/pdf-view.el index bba73fb..778284e 100644 --- a/lisp/pdf-view.el +++ b/lisp/pdf-view.el @@ -96,6 +96,13 @@ dis-/advantages of imagemagick and png." :group 'pdf-view :group 'pdf-tools-faces) +(defface pdf-view-rectangle + '((((background dark)) (:inherit highlight)) + (((background light)) (:inherit highlight))) + "Face used to determine the colors of the highlighted rectangle." + :group 'pdf-view + :group 'pdf-tools-faces) + (defcustom pdf-view-midnight-colors '("#839496" . "#002b36" ) "Colors used when `pdf-view-midnight-minor-mode' is activated. @@ -136,7 +143,14 @@ See also `pdf-view-change-page-hook' and (defvar-local pdf-view-active-region nil "The active region as a list of edges. -Edge values are image coordinates.") +Edge values are relative coordinates.") + +(defvar-local pdf-view--have-rectangle-region nil + "Non-nil if the region is currently rendered as a rectangle. + +This variable is set in `pdf-view-mouse-set-region' and used in +`pdf-view-mouse-extend-region' to determine the right choice +regarding display of the region in the later function.") (defvar-local pdf-view--buffer-file-name nil "Local copy of remote file or nil.") @@ -218,6 +232,7 @@ Edge values are image coordinates.") (define-key map (kbd "r") 'revert-buffer) ;; Region (define-key map [down-mouse-1] 'pdf-view-mouse-set-region) + (define-key map [M-down-mouse-1] 'pdf-view-mouse-set-region-rectangle) (define-key map [C-down-mouse-1] 'pdf-view-mouse-extend-region) (define-key map [remap kill-region] 'pdf-view-kill-ring-save) (define-key map [remap kill-ring-save] 'pdf-view-kill-ring-save) @@ -225,8 +240,9 @@ Edge values are image coordinates.") ;; Other (define-key map (kbd "C-c C-d") 'pdf-view-dark-minor-mode) (define-key map (kbd "m") 'pdf-view-position-to-register) - (define-key map (kbd "'") 'pdf-view-jump-to-register-command) + + (define-key map (kbd "C-c C-i") 'pdf-view-extract-region-image) ;; Rendering (define-key map (kbd "C-c C-r m") 'pdf-view-midnight-minor-mode) (define-key map (kbd "C-c C-r p") 'pdf-view-printer-minor-mode) @@ -1014,23 +1030,31 @@ Deactivate the region if DEACTIVATE-P is non-nil." (deactivate-mark) (pdf-view-redisplay t))) -(defun pdf-view-mouse-set-region (ev &optional allow-extend) - "Selects a region of text using the mouse." +(defun pdf-view-mouse-set-region (event &optional allow-extend-p + render-rectangle-p) + "Selects a region of text using the mouse. + +Allow for stacking of regions, if ALLOW-EXTEND-P is non-nil. +Highlight the region with a rectangle if RENDER-RECTANGLE-P +is non-nil, otherwise highlight text only. + +Stores the region in `pdf-view-active-region'." (interactive "@e") - (unless (and (eventp ev) - (mouse-event-p ev)) - (signal 'wrong-type-argument (list 'mouse-event-p ev))) - (unless (and allow-extend + (setq pdf-view--have-rectangle-region render-rectangle-p) + (unless (and (eventp event) + (mouse-event-p event)) + (signal 'wrong-type-argument (list 'mouse-event-p event))) + (unless (and allow-extend-p (or (null (get this-command 'pdf-view-region-window)) (equal (get this-command 'pdf-view-region-window) (selected-window)))) (pdf-view-deactivate-region)) (put this-command 'pdf-view-region-window (selected-window)) - (unless (posn-image (event-start ev)) + (unless (posn-image (event-start event)) (error "No page at this position")) (let* ((window (selected-window)) - (beg (posn-object-x-y (event-start ev))) + (beg (posn-object-x-y (event-start event))) pdf-view-continuous region) (when (pdf-util-track-mouse-dragging (event 0.15) @@ -1039,36 +1063,50 @@ Deactivate the region if DEACTIVATE-P is non-nil." (when (and (eq window (posn-window pos)) (posn-image pos)) (setq region - (list (min (car beg) (car end)) - (min (cdr beg) (cdr end)) - (max (car beg) (car end)) - (max (cdr beg) (cdr end)))) + (pdf-util-scale-pixel-to-relative + (list (min (car beg) (car end)) + (min (cdr beg) (cdr end)) + (max (car beg) (car end)) + (max (cdr beg) (cdr end))))) (pdf-view-display-region - (cons region pdf-view-active-region)) + (cons region pdf-view-active-region) + render-rectangle-p) (pdf-util-scroll-to-edges region)))) (push region pdf-view-active-region) (pdf-view--push-mark)))) -(defun pdf-view-mouse-extend-region (ev) +(defun pdf-view-mouse-extend-region (event) + "Extend the currently active region." (interactive "@e") - (pdf-view-mouse-set-region ev t)) + (pdf-view-mouse-set-region + event t pdf-view--have-rectangle-region)) -(defun pdf-view-display-region (&optional region) +(defun pdf-view-mouse-set-region-rectangle (event) + "Like `pdf-view-mouse-set-region' but displays as a rectangle. + +This is more useful for commands like +`pdf-view-extract-region-image'." + (interactive "@e") + (pdf-view-mouse-set-region event nil t)) + +(defun pdf-view-display-region (&optional region rectangle-p) (unless region (pdf-view-assert-active-region) (setq region pdf-view-active-region)) - (let ((colors (pdf-util-face-colors 'pdf-view-region - (bound-and-true-p pdf-view-dark-minor-mode))) + (let ((colors (pdf-util-face-colors + (if rectangle-p 'pdf-view-rectangle 'pdf-view-region) + (bound-and-true-p pdf-view-dark-minor-mode))) (page (pdf-view-current-page)) (width (car (pdf-view-image-size)))) (pdf-view-display-image (pdf-view-create-image - (pdf-info-renderpage-text-regions - page width - nil nil - `(,(car colors) - ,(cdr colors) - ,@(mapcar 'pdf-util-scale-pixel-to-relative region))))))) + (if rectangle-p + (pdf-info-renderpage-highlight + page width nil + `(,(car colors) ,(cdr colors) 0.35 ,@region)) + (pdf-info-renderpage-text-regions + page width nil nil + `(,(car colors) ,(cdr colors) ,@region))))))) (defun pdf-view-kill-ring-save () "Copy the region to the `kill-ring'." @@ -1082,9 +1120,8 @@ Deactivate the region if DEACTIVATE-P is non-nil." "Mark the whole page." (interactive) (pdf-view-deactivate-region) - (let ((size (pdf-view-image-size))) - (setq pdf-view-active-region - (list (list 0 0 (car size) (cdr size))))) + (setq pdf-view-active-region + (list (list 0 0 1 1))) (pdf-view--push-mark) (pdf-view-display-region)) @@ -1092,12 +1129,72 @@ Deactivate the region if DEACTIVATE-P is non-nil." "Return the text of the active region as a list of strings." (pdf-view-assert-active-region) (mapcar - (lambda (r) - (pdf-info-gettext - (pdf-view-current-page) - (pdf-util-scale-pixel-to-relative r))) + (apply-partially 'pdf-info-gettext (pdf-view-current-page)) pdf-view-active-region)) +(defun pdf-view-extract-region-image (regions &optional page size + output-buffer no-display-p) + "Create a PNG image of REGIONS. + +REGIONS have the same form as `pdf-view-active-region', which +see. PAGE and size are the page resp. base-size of the image +from which the image-regions will be created; they default to +`pdf-view-current-page' resp. `pdf-view-image-size'. + +Put the image in OUTPUT-BUFFER, defaulting to \"*PDF region +image*\" and display it, unless NO-DISPLAY-P is non-nil. + +In case of multiple regions, the resulting image is constructed +by joining them horizontally." + + (interactive + (list (if (pdf-view-active-region-p) + (pdf-view-active-region t) + '((0 0 1 1))))) + (unless page + (setq page (pdf-view-current-page))) + (unless size + (setq size (pdf-view-image-size))) + (unless output-buffer + (setq output-buffer (get-buffer-create "*PDF region image*"))) + (let* ((temps (mapcar (lambda (_) (make-temp-file "pdf-view")) + (cons nil (cons nil regions)))) + (whole (car temps)) + (result (cadr temps)) + (slices (cddr temps))) + (unwind-protect + (progn + (write-region (pdf-info-renderpage page (car size)) + nil whole nil 'no-message) + (if (and (= (length regions) 1) + (equal (car regions) + '(0 0 1 1))) + (setq result whole) + (cl-mapcar (lambda (r slice) + (pdf-util-convert + whole slice + :commands '("-crop" "%g") + :apply (list r))) + (pdf-util-scale regions size 'round) + slices) + (if (cdr slices) + (pdf-util-convert + (car slices) + result + :commands (append (cdr slices) + (list "-append")) + :apply '((0 0 0 0))) + (setq result (car slices)))) + (with-current-buffer output-buffer + (let ((inhibit-read-only t)) + (erase-buffer)) + (insert-file-contents-literally result) + (image-mode) + (unless no-display-p + (display-buffer (current-buffer))))) + (dolist (f temps) + (when (file-exists-p f) + (delete-file f)))))) ;; * ================================================================== * ;; * Bookmark + Register Integration |
