emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] shr-fontified 1da4c13 1/4: Implement a faster pixel-based


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] shr-fontified 1da4c13 1/4: Implement a faster pixel-based text algorithm
Date: Fri, 30 Jan 2015 05:46:15 +0000

branch: shr-fontified
commit 1da4c132935b57e20aea78d3bb5e264b07ae5717
Author: Lars Magne Ingebrigtsen <address@hidden>
Commit: Lars Magne Ingebrigtsen <address@hidden>

    Implement a faster pixel-based text algorithm
    
    * net/shr.el (shr-move-to-pixel-column): Removed.
    (shr-insert): Don't do folding on insertion.
    (shr-fold-lines): New function.
    (shr-fold-line): Ditto.
    (shr-glyph-widths): New function.
    
    * net/eww.el (eww-display-html): Use shr's body renderer.  They
    were identical.
---
 lisp/ChangeLog  |   11 ++++
 lisp/net/eww.el |   10 ----
 lisp/net/shr.el |  156 ++++++++++++++++++++++++++++++-------------------------
 3 files changed, 96 insertions(+), 81 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index cfaeb9d..18914ce 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,14 @@
+2015-01-30  Lars Ingebrigtsen  <address@hidden>
+
+       * net/eww.el (eww-display-html): Use shr's body renderer.  They
+       were identical.
+
+       * net/shr.el (shr-move-to-pixel-column): Removed.
+       (shr-insert): Don't do folding on insertion.
+       (shr-fold-lines): New function.
+       (shr-fold-line): Ditto.
+       (shr-glyph-widths): New function.
+
 2015-01-28  Lars Ingebrigtsen  <address@hidden>
 
        * net/shr.el (shr-pixel-column, shr-string-pixel-width)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index ec7a0ba..1588d6a 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -409,7 +409,6 @@ See the `eww-search-prefix' variable for the search engine 
used."
               (form . eww-tag-form)
               (input . eww-tag-input)
               (textarea . eww-tag-textarea)
-              (body . eww-tag-body)
               (select . eww-tag-select)
               (link . eww-tag-link)
               (a . eww-tag-a))))
@@ -495,15 +494,6 @@ See the `eww-search-prefix' variable for the search engine 
used."
              (replace-regexp-in-string "[ \t\r\n]+" " " (dom-text dom))))
   (eww-update-header-line-format))
 
-(defun eww-tag-body (dom)
-  (let* ((start (point))
-        (fgcolor (or (dom-attr dom 'fgcolor) (dom-attr dom 'text)))
-        (bgcolor (dom-attr dom 'bgcolor))
-        (shr-stylesheet (list (cons 'color fgcolor)
-                              (cons 'background-color bgcolor))))
-    (shr-generic dom)
-    (shr-colorize-region start (point) fgcolor bgcolor)))
-
 (defun eww-display-raw (buffer &optional encode)
   (let ((data (buffer-substring (point) (point-max))))
     (unless (buffer-live-p buffer)
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index c25a656..6328796 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -207,7 +207,7 @@ DOM should be a parse tree as generated by
        (shr-base nil)
        (shr-depth 0)
        (shr-warning nil)
-       (shr-internal-width (or shr-width (- (window-pixel-width) 20))))
+       (shr-internal-width (or shr-width (- (window-pixel-width) 40))))
     (shr-descend dom)
     (shr-remove-trailing-whitespace start (point))
     (when shr-warning
@@ -466,19 +466,7 @@ size, and full-buffer size."
     (insert string)
     (shr-pixel-column)))
 
-(defun shr-move-to-pixel-column (pixel)
-  (move-to-column (/ pixel 10))
-  (if (> (shr-pixel-column) pixel)
-      (while (and (> (shr-pixel-column) pixel)
-                 (not (bolp)))
-       (forward-char -1))
-    (while (and (< (shr-pixel-column) pixel)
-               (not (eolp)))
-      (forward-char 1)))
-  (shr-pixel-column))
-
 (defun shr-insert (text)
-  (setq text (propertize text 'face 'variable-pitch))
   (when (and (eq shr-state 'image)
             (not (bolp))
             (not (string-match "\\`[ \t\n]+\\'" text)))
@@ -492,62 +480,85 @@ size, and full-buffer size."
               (not (bolp))
               (not (eq (char-after (1- (point))) ? )))
       (insert " "))
-    (dolist (elem (split-string text "[ \f\t\n\r\v ]+" t))
-      (when (and (bolp)
-                (> shr-indentation 0))
-       (shr-indent))
-      ;; No space is needed behind a wide character categorized as
-      ;; kinsoku-bol, between characters both categorized as nospace,
-      ;; or at the beginning of a line.
-      (let (prev)
-       (when (and (> (current-column) shr-indentation)
-                  (eq (preceding-char) ? )
-                  (or (= (line-beginning-position) (1- (point)))
-                      (and (shr-char-breakable-p
-                            (setq prev (char-after (- (point) 2))))
-                           (shr-char-kinsoku-bol-p prev))
-                      (and (shr-char-nospace-p prev)
-                           (shr-char-nospace-p (aref elem 0)))))
-         (delete-char -1)))
-      ;; The shr-start is a special variable that is used to pass
-      ;; upwards the first point in the buffer where the text really
-      ;; starts.
-      (unless shr-start
-       (setq shr-start (point)))
-      (insert elem)
-      (setq shr-state nil)
-      (let (found)
-       (while (and (> (shr-pixel-column) shr-internal-width)
-                   (> shr-internal-width 0)
-                   (progn
-                     (setq found (shr-find-fill-point))
-                     (not (eolp))))
-         (when (eq (preceding-char) ? )
-           (delete-char -1))
-         (insert "\n")
-         (unless found
-           ;; No space is needed at the beginning of a line.
-           (when (eq (following-char) ? )
-             (delete-char 1)))
-         (when (> shr-indentation 0)
-           (shr-indent))
-         (end-of-line))
-       (if (<= (shr-pixel-column) shr-internal-width)
-           (insert " ")
-         ;; In case we couldn't get a valid break point (because of a
-         ;; word that's longer than `shr-internal-width'), just break anyway.
-         (insert "\n")
-         (when (> shr-indentation 0)
-           (shr-indent)))))
-    (unless (string-match "[ \t\r\n ]\\'" text)
-      (delete-char -1)))))
-
-(defun shr-find-fill-point ()
-  (when (> (shr-move-to-pixel-column shr-internal-width) shr-internal-width)
-    (backward-char 1))
+    (let ((start (point))
+         (bolp (bolp)))
+      (insert text)
+      (save-restriction
+       (narrow-to-region start (point))
+       (goto-char start)
+       (when (looking-at "[ \t\n ]+")
+         (replace-match "" t t))
+       (while (re-search-forward "[ \t\n ]+" nil t)
+         (replace-match " " t t))
+       (goto-char (point-max)))
+      ;; We may have removed everything we inserted if if was just
+      ;; spaces.
+      (unless (= start (point))
+       ;; Mark all lines that should possibly be folded afterwards.
+       (when bolp
+         (put-text-property start (1+ start)
+                            'shr-indentation shr-indentation))
+       (put-text-property start (point) 'face 'variable-pitch))))))
+
+(defun shr-fold-lines (start end)
+  (save-restriction
+    (narrow-to-region start end)
+    (goto-char start)
+    (when (get-text-property (point) 'shr-indentation)
+      (shr-fold-line))
+    (while (setq start (next-single-property-change start 'shr-indentation))
+      (goto-char start)
+      (shr-fold-line))
+    (goto-char (point-max))))
+
+(defun shr-fold-line ()
+  (let ((start (point))
+       (indentation (get-text-property (point) 'shr-indentation)))
+    (put-text-property start (1+ start) 'shr-indentation nil)
+    (when (> indentation 0)
+      (insert (make-string indentation ?\s)))
+    (let ((widths (shr-glyph-widths start (line-end-position)))
+         (this-width 0)
+         (i 0))
+      (while (< i (length widths))
+       (while (and (< i (length widths))
+                   (< this-width shr-internal-width))
+         (setq this-width (+ this-width (aref widths i))
+               i (1+ i))
+         (unless (eobp)
+           (forward-char 1)))
+       (when (< i (length widths))
+         ;; We have to do some folding.  First find the first
+         ;; previous point suitable for folding.
+         (let ((end (point)))
+           (shr-find-fill-point (line-beginning-position))
+           ;; Adjust the index to where we moved when finding the
+           ;; fill point.
+           (setq i (+ i (- end (point)))
+                 this-width 0)
+           (insert "\n")))))))
+
+(defun shr-glyph-widths (start end)
+  (let ((widths (make-vector (- end start) 0))
+       (string (buffer-substring start end))
+       (start 0))
+    (while (< start (length string))
+      (let ((glyphs (font-get-glyphs (font-at start nil string)
+                                    start (1+ start) string)))
+       (aset widths
+             start
+             (if (not (aref glyphs 0))
+                 ;; If we have a degenerate font, just say "10".
+                 10
+               (aref (aref glyphs 0) 4))))
+      (setq start (1+ start)))
+    widths))
+
+(defun shr-find-fill-point (start)
   (let ((bp (point))
+       (end (point))
        failed)
-    (while (not (or (setq failed (<= (current-column) shr-indentation))
+    (while (not (or (setq failed (<= (point) start))
                    (eq (preceding-char) ? )
                    (eq (following-char) ? )
                    (shr-char-breakable-p (preceding-char))
@@ -578,12 +589,12 @@ size, and full-buffer size."
         (while (and (not (memq (preceding-char) (list ?\C-@ ?\n ? )))
                     (shr-char-kinsoku-eol-p (preceding-char)))
           (backward-char 1))
-        (when (setq failed (<= (current-column) shr-indentation))
+        (when (setq failed (<= (point) start))
           ;; There's no breakable point that doesn't violate kinsoku,
           ;; so we look for the second best position.
           (while (and (progn
                         (forward-char 1)
-                        (<= (shr-pixel-column) shr-internal-width))
+                        (<= (point) end))
                       (progn
                         (setq bp (point))
                         (shr-char-kinsoku-eol-p (following-char)))))
@@ -598,7 +609,7 @@ size, and full-buffer size."
                      (not (memq (preceding-char) (list ?\C-@ ?\n ? )))
                      (or (shr-char-kinsoku-eol-p (preceding-char))
                          (shr-char-kinsoku-bol-p (following-char)))))))
-        (when (setq failed (<= (current-column) shr-indentation))
+        (when (setq failed (<= (point) start))
           ;; There's no breakable point that doesn't violate kinsoku,
           ;; so we go to the second best position.
           (if (looking-at "\\(\\c<+\\)\\c<")
@@ -1038,7 +1049,8 @@ ones, in case fg and bg are nil."
         (shr-stylesheet (list (cons 'color fgcolor)
                               (cons 'background-color bgcolor))))
     (shr-generic dom)
-    (shr-colorize-region start (point) fgcolor bgcolor)))
+    (shr-colorize-region start (point) fgcolor bgcolor)
+    (shr-fold-lines start (point))))
 
 (defun shr-tag-style (_dom)
   )
@@ -1766,6 +1778,8 @@ The preference is a float determined from 
`shr-prefer-media-type'."
       (let ((shr-internal-width width)
            (shr-indentation 0))
        (shr-descend dom))
+      (let ((shr-internal-width width))
+       (shr-fold-lines (point-min) (point-max)))
       ;; Delete padding at the bottom of the TDs.
       (delete-region
        (point)



reply via email to

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