[mcclim-cvs] CVS update: mcclim/recording.lisp mcclim/stream-output.lisp

Christophe Rhodes crhodes at common-lisp.net
Sat Aug 13 14:28:24 UTC 2005


Update of /project/mcclim/cvsroot/mcclim
In directory common-lisp.net:/tmp/cvs-serv4334

Modified Files:
	recording.lisp stream-output.lisp 
Log Message:
Commit working version of text-bounding-rectangle* stuff, as trailed on 
mcclim-devel 2005-08-12.  Basically, this is needed because the drawn
area for left-to-right text need not lie between (x,y-ascent) and
(x+width,y+descent).  (No doubt other text drawing directions suffer 
from the same problem, but they're not yet implemented in McCLIM).

New per-medium function TEXT-BOUNDING-RECTANGLE* which actually returns
the bounding-rectangle* of what is drawn (cf. TEXT-WIDTH, which doesn't 
do anything of the sort).  Use it in DEF-GRECORDING DRAW-TEXT, and in 
add-{string,character}-to-output-record, to properly adjust the output 
record coordinates.  While we're at it, fix the bounding box for 
:y-align :center DRAW-TEXT.

Implement this per-medium function for the CLX backend, for the
experimental freetype text handling, and for postscript (tested using 
Climacs, Tabcode and clim-demo::postscript-text).  This patch was mostly 
motivated by the observation that incremental redisplay in climacs 
windows using the freetype backend caused graphical artifacts to appear 
over time, thanks to glyphs drawing outside the output record bounding 
rectangles.

Breaks:
 * CLX backend with #+unicode (clisp?)
 * Beagle backend
 * OpenGL backend
(please fix!)

Date: Sat Aug 13 16:28:21 2005
Author: crhodes

Index: mcclim/recording.lisp
diff -u mcclim/recording.lisp:1.118 mcclim/recording.lisp:1.119
--- mcclim/recording.lisp:1.118	Tue Feb 15 12:28:11 2005
+++ mcclim/recording.lisp	Sat Aug 13 16:28:19 2005
@@ -1644,7 +1644,7 @@
 (def-grecording draw-text ((gs-text-style-mixin) string point-x point-y start end
 			   align-x align-y toward-x toward-y transform-glyphs) ()
   ;; FIXME!!! Text direction.
-  ;; Multiple lines?
+  ;; FIXME: Multiple lines.
  (let* ((text-style (graphics-state-text-style graphic))
 	(width (if (characterp string)
 		   (stream-character-width stream string :text-style text-style)
@@ -1654,27 +1654,26 @@
         (ascent (text-style-ascent text-style (sheet-medium stream)))
         (descent (text-style-descent text-style (sheet-medium stream)))
         (height (+ ascent descent))
-	(transform (medium-transformation medium))
-        left top right bottom)
+	(transform (medium-transformation medium)))
    (setf (values point-x point-y)
 	 (transform-position transform point-x point-y))
-   (ecase align-x
-     (:left (setq left point-x
-                  right (+ point-x width)))
-     (:right (setq left (- point-x width)
-                   right point-x))
-     (:center (setq left (- point-x (round width 2))
-                    right (+ point-x (round width 2)))))
-   (ecase align-y
-     (:baseline (setq top (- point-y ascent)
-                      bottom (+ point-y descent)))
-     (:top (setq top point-y
-                 bottom (+ point-y height)))
-     (:bottom (setq top (- point-y height)
-                    bottom point-y))
-     (:center (setq top (- point-y (floor height 2))
-                    bottom (+ point-y (ceiling height 2)))))
-   (values left top right bottom)))
+   (multiple-value-bind (left top right bottom)
+       (text-bounding-rectangle* medium string 
+                                 :start start :end end :text-style text-style)
+     (ecase align-x
+       (:left (incf left point-x) (incf right point-x))
+       (:right (incf left (- point-x width)) (incf right (- point-x width)))
+       (:center (incf left (- point-x (round width 2)))
+                (incf right (- point-x (round width 2)))))
+     (ecase align-y
+       (:baseline (incf top point-y) (incf bottom point-y))
+       (:top (incf top (+ point-y ascent))
+             (incf bottom (+ point-y ascent)))
+       (:bottom (incf top (- point-y descent))
+                (incf bottom (- point-y descent)))
+       (:center (incf top (+ point-y (ceiling (- ascent descent) 2)))
+                (incf bottom (+ point-y (ceiling (- ascent descent) 2)))))
+     (values left top right bottom))))
 
 (defmethod* (setf output-record-position) :around
     (nx ny (record draw-text-output-record))
@@ -1736,6 +1735,15 @@
    (baseline :initform 0)
    (width :initform 0)
    (max-height :initform 0)
+   ;; FIXME (or rework this comment): CLIM does not separate the
+   ;; notions of the text width and the bounding box; however, we need
+   ;; to, because some fonts will render outside the logical
+   ;; coordinates defined by the start position and the width.  LEFT
+   ;; and RIGHT here (and below) deal with this in a manner completely
+   ;; hidden from the user.  (should we export
+   ;; TEXT-BOUNDING-RECTANGLE*?)
+   (left :initarg :start-x)
+   (right :initarg :start-x)
    (start-x :initarg :start-x)
    (start-y :initarg :start-y)
    (end-x :initarg :start-x)
@@ -1757,12 +1765,14 @@
     ((record standard-text-displayed-output-record)
      (record2 standard-text-displayed-output-record))
   (with-slots
-	(initial-x1 initial-y1 start-x start-y end-x end-y wrapped strings)
+	(initial-x1 initial-y1 start-x start-y left right end-x end-y wrapped strings)
       record2
     (and (coordinate= (slot-value record 'initial-x1) initial-x1)
 	 (coordinate= (slot-value record 'initial-y1) initial-y1)
 	 (coordinate= (slot-value record 'start-x) start-x)
 	 (coordinate= (slot-value record 'start-y) start-y)
+         (coordinate= (slot-value record 'left) left)
+         (coordinate= (slot-value record 'right) right)
 	 (coordinate= (slot-value record 'end-x) end-x)
 	 (coordinate= (slot-value record 'end-y) end-y)
 	 (eq (slot-value record 'wrapped) wrapped)
@@ -1835,20 +1845,21 @@
 
 (defmethod tree-recompute-extent
     ((text-record standard-text-displayed-output-record))
-  (with-standard-rectangle* (:x1 x1 :y1 y1)
+  (with-standard-rectangle* (:y1 y1)
       text-record
-    (with-slots (width max-height)
+    (with-slots (max-height left right)
 	text-record
       (setf (rectangle-edges* text-record)
-	    (values x1 y1
-		    (coordinate (+ x1 width))
-		    (coordinate (+ y1 max-height))))))
+	    (values (coordinate left)
+                    y1 
+                    (coordinate right)
+                    (coordinate (+ y1 max-height))))))
   text-record)
 
 (defmethod add-character-output-to-text-record ; XXX OAOO with ADD-STRING-...
     ((text-record standard-text-displayed-output-record)
      character text-style char-width height new-baseline)
-  (with-slots (strings baseline width max-height start-y end-x end-y medium)
+  (with-slots (strings baseline width max-height left right start-y end-x end-y medium)
       text-record
     (if (and strings
 	     (let ((string (last1 strings)))
@@ -1868,11 +1879,18 @@
 					   :element-type 'character
 					   :adjustable t
 					   :fill-pointer t)))))
-    (setq baseline (max baseline new-baseline)
-	  end-x (+ end-x char-width)
-	  max-height (max max-height height)
-	  end-y (max end-y (+ start-y max-height))
-	  width (+ width char-width)))
+    (multiple-value-bind (minx miny maxx maxy)
+        (text-bounding-rectangle* medium character :text-style text-style)
+      (declare (ignore miny maxy))
+      (setq baseline (max baseline new-baseline)
+            ;; KLUDGE: note END-X here is really START-X of the new
+            ;; string
+            left (min left (+ end-x minx))
+            end-x (+ end-x char-width)
+            right (+ end-x (max 0 (- maxx char-width)))
+            max-height (max max-height height)
+            end-y (max end-y (+ start-y max-height))
+            width (+ width char-width))))
   (tree-recompute-extent text-record))
 
 (defmethod add-string-output-to-text-record
@@ -1886,7 +1904,7 @@
                                             (aref string start)
                                             text-style
                                             string-width height new-baseline))
-      (t (with-slots (strings baseline width max-height start-y end-x end-y
+      (t (with-slots (strings baseline width max-height left right start-y end-x end-y
 		      medium)
 	     text-record
 	   (let ((styled-string (make-instance
@@ -1901,12 +1919,21 @@
 	     (nconcf strings (list styled-string))
 	     (replace (styled-string-string styled-string) string
 		      :start2 start :end2 end))
-	   (setq baseline (max baseline new-baseline)
-		 end-x (+ end-x string-width)
-		 max-height (max max-height height)
-		 end-y (max end-y (+ start-y max-height))
-		 width (+ width string-width)))
-       (tree-recompute-extent text-record)))))
+           (multiple-value-bind (minx miny maxx maxy)
+               (text-bounding-rectangle* medium string
+                                         :text-style text-style
+                                         :start start :end end)
+             (declare (ignore miny maxy))
+             (setq baseline (max baseline new-baseline)
+                   ;; KLUDGE: note that END-X here really means
+                   ;; START-X of the new string.
+                   left (min left (+ end-x minx))
+                   end-x (+ end-x string-width)
+                   right (+ end-x (max 0 (- maxx string-width)))
+                   max-height (max max-height height)
+                   end-y (max end-y (+ start-y max-height))
+                   width (+ width string-width))))
+         (tree-recompute-extent text-record)))))
 
 (defmethod text-displayed-output-record-string
     ((record standard-text-displayed-output-record))


Index: mcclim/stream-output.lisp
diff -u mcclim/stream-output.lisp:1.55 mcclim/stream-output.lisp:1.56
--- mcclim/stream-output.lisp:1.55	Thu Apr 21 04:43:19 2005
+++ mcclim/stream-output.lisp	Sat Aug 13 16:28:20 2005
@@ -358,9 +358,7 @@
 	    (unless (= start split)
 	      (stream-write-output stream
 				   string
-				   (if (eql end split)
-				       width
-				       nil)
+                                   nil
 				   start split)
 	      (setq cx (+ cx width))	      
           (with-slots (x y) (stream-text-cursor stream)




More information about the Mcclim-cvs mailing list