render: Refactor sprite rendering.
authorDavid Thompson <dthompson2@worcester.edu>
Wed, 17 Jan 2018 17:01:41 +0000 (12:01 -0500)
committerDavid Thompson <dthompson2@worcester.edu>
Wed, 17 Jan 2018 17:01:41 +0000 (12:01 -0500)
* chickadee/render/texture.scm (<texture-region>): Delete type.
(<texture>)[width, height, gl-size]: Delete fields.
[parent, rect, gl-rect]: Add fields.
(texture-region?): Rewrite.
(make-texture, null-texture): Use new texture constructor.
(make-texture-region): Rewrite in terms of <texture> type.
(list->texture-atlas, split-texture): Use new texture region
constructor.
* chickadee/render/sprite.scm (draw-sprite*): New procedure.
(draw-sprite): Rewrite in terms of draw-sprite*.
(draw-nine-patch*): New procedure.
(draw-nine-patch): Rewrite in terms of draw-nine-patch*.
* chickadee/render/font.scm (draw-text*): New procedure.
(draw-text): Rewrite in terms of draw-text*.
* doc/api.texi: Update draw-sprite, draw-nine-patch, and draw-text
docs.

chickadee/render/font.scm
chickadee/render/sprite.scm
chickadee/render/texture.scm
doc/api.texi

index bac5056..4bb44ce 100644 (file)
@@ -44,6 +44,7 @@
             font-line-height
             font-bold?
             font-italic?
+            draw-text*
             draw-text))
 
 (define-record-type <font-char>
@@ -252,7 +253,7 @@ extension must be either .xml or .fnt."
                          (x-advance (attr node 'xadvance string->number))
                          (page (or (attr node 'page string->number) 0))
                          (region (make-texture-region (hash-ref pages page)
-                                                      x y width height))
+                                                      (make-rect x y width height)))
                          (char (make-font-char id
                                                region
                                                (vec2 x-offset y-offset)
@@ -295,38 +296,48 @@ extension must be either .xml or .fnt."
 (define (font-ref font char)
   (hashv-ref (font-chars font) char))
 
-(define %default-offset (vec2 0.0 0.0))
-
-(define draw-text
+(define draw-text*
   (let ((cursor (vec2 0.0 0.0))
-        (char-pos (vec2 0.0 0.0)))
-    (lambda* (font text position #:key
-                   (rotation 0)
-                   (scale 1.0)
-                   matrix
-                   (offset %default-offset)
-                   (blend-mode 'alpha))
-      "Draw the string TEXT with the first character starting at
-POSITION using FONT."
+        (rect (make-rect 0.0 0.0 0.0 0.0)))
+    (lambda* (font text matrix #:key (blend-mode 'alpha))
       ;; TODO: Respect kerning.
       (define (render-char c)
         (let* ((char (font-ref font c))
+               (texture (font-char-texture-region char))
                (dimensions (font-char-dimensions char))
                (offset (font-char-offset char)))
-          (set-vec2-x! char-pos (+ (vec2-x cursor) (vec2-x offset)))
-          (set-vec2-y! char-pos (+ (vec2-y cursor) (vec2-y offset)))
-          (draw-sprite (font-char-texture-region char)
-                       char-pos
-                       #:offset offset
-                       #:scale scale
-                       #:rotation rotation
-                       #:matrix matrix
-                       #:blend-mode blend-mode)
+          (set-rect-x! rect (+ (vec2-x cursor) (vec2-x offset)))
+          (set-rect-y! rect (+ (vec2-y cursor) (vec2-y offset)))
+          (set-rect-width! rect (vec2-x dimensions))
+          (set-rect-height! rect (vec2-y dimensions))
+          (draw-sprite* texture rect matrix #:blend-mode blend-mode)
           ;; Move forward to where the next character needs to be drawn.
           (set-vec2-x! cursor
                        (+ (vec2-x cursor)
                           (vec2-x
                            (font-char-advance char))))))
-      (vec2-copy! position cursor) ; initialize position
-      (with-batched-sprites
-       (string-for-each render-char text)))))
+      (set-vec2-x! cursor 0.0)
+      (set-vec2-y! cursor 0.0)
+      (string-for-each render-char text))))
+
+(define %default-scale (vec2 1.0 1.0))
+(define %null-vec (vec2 0.0 0.0))
+
+(define draw-text
+  (let ((matrix (make-null-matrix4)))
+    (lambda* (font
+              text
+              position
+              #:key
+              (origin %null-vec2)
+              (rotation 0)
+              (scale %default-scale)
+              (blend-mode 'alpha))
+      "Draw the string TEXT with the first character starting at
+POSITION using FONT."
+      (matrix4-2d-transform! matrix
+                             #:origin origin
+                             #:position position
+                             #:rotation rotation
+                             #:scale scale)
+      (draw-text* font text matrix #:blend-mode blend-mode))))
index 38b1594..c284ff4 100644 (file)
   #:use-module (chickadee render shader)
   #:use-module (chickadee render texture)
   #:use-module (chickadee render buffer)
-  #:export (draw-sprite
+  #:export (draw-sprite*
+            draw-sprite
             with-batched-sprites
+            draw-nine-patch*
             draw-nine-patch))
 
 (define default-shader
@@ -325,190 +327,107 @@ void main (void) {
         (lambda ()
           (set! *batch?* #f)))))
 
-(define texture-gl-size
-  (@@ (chickadee render texture) texture-gl-size))
-(define texture-region-gl-size
-  (@@ (chickadee render texture) texture-region-gl-size))
-(define texture-region-gl-rect
-  (@@ (chickadee render texture) texture-region-gl-rect))
+(define* (draw-sprite* texture rect matrix #:key
+                       (blend-mode 'alpha)
+                       (texcoords (texture-gl-rect texture))
+                       (shader (force default-shader)))
+  (if *batch?*
+      (draw-sprite-batched texture rect matrix blend-mode
+                           shader texcoords)
+      (draw-sprite-unbatched texture rect matrix blend-mode
+                             shader texcoords)))
 
-(define %default-texcoords (make-rect 0.0 0.0 1.0 1.0))
-(define %default-offset (vec2 0.0 0.0))
+(define %null-vec2 (vec2 0.0 0.0))
+(define %default-scale (vec2 1.0 1.0))
 
 (define draw-sprite
-  (let ((rect (make-rect 0.0 0.0 0.0 0.0))
-        (tmp-matrix (make-null-matrix4))
-        (%matrix (make-null-matrix4)))
+  (let ((matrix (make-null-matrix4)))
     (lambda* (texture
-              region
+              position
               #:key
-              (scale 1.0)
-              (rotation 0)
-              matrix
-              (offset %default-offset)
+              (origin %null-vec2)
+              (scale %default-scale)
+              (rotation 0.0)
               (blend-mode 'alpha)
-              (texcoords
-               (if (texture-region? texture)
-                   (texture-region-gl-rect texture)
-                   %default-texcoords))
+              (rect (texture-rect texture))
               (shader (force default-shader)))
-      "Draw TEXTURE over the area defined by the rect REGION.  Instead
-of a rect, REGION may be a vec2 representing the position of the
-sprite, in which case the width and height of the sprite corresponds
-to the size of the texture.  TEXTURE may be a texture or a texture
-region.
+      "Draw TEXTURE at POSITION.
 
+Optionally, other transformations may be applied to the sprite.
 ROTATION specifies the angle to rotate the sprite, in radians.  SCALE
-specifies the scaling factor.  No scaling or rotation is applied by
-default.  Alternatively, MATRIX may be specified, in which case
-ROTATION and SCALE are ignored and the given transformation matrix is
-used instead.  All transformations are applied relative to the lower
-left corner of the sprite by default.  This can be changed by
-specifying an OFFSET vector.
+specifies the scaling factor as a 2D vector.  All transformations are
+applied relative to ORIGIN, a 2D vector.
+
+By default, alpha blending is used but can be changed by specifying
+BLEND-MODE.
 
-By default, alpha
-blending is used but can be changed by setting BLEND-MODE.  Finally,
-advanced users may pass SHADER to change the way the sprite is
+Advanced users may pass SHADER to change the way the sprite is
 rendered entirely."
-      (let* ((size (if (texture-region? texture)
-                       (texture-region-gl-size texture)
-                       (texture-gl-size texture)))
-             (texture (if (texture-region? texture)
-                          (texture-region-texture texture)
-                          texture))
-             (matrix (cond
-                      (matrix matrix) ; user-specified matrix
-                      ((or rotation scale) ; compute matrix on-the-fly
-                       (matrix4-identity! %matrix)
-                       (unless (zero? rotation)
-                         (matrix4-rotate-z! tmp-matrix rotation)
-                         (matrix4-mult! %matrix %matrix tmp-matrix))
-                       (unless (= scale 1.0)
-                         (matrix4-scale! tmp-matrix scale)
-                         (matrix4-mult! %matrix %matrix tmp-matrix))
-                       (matrix4-translate! tmp-matrix region)
-                       (matrix4-mult! %matrix %matrix tmp-matrix)
-                       %matrix)
-                      ;; No transformation needed, in which case we
-                      ;; use no matrix at all in order to save cycles
-                      ;; and not waste time multiplying against the
-                      ;; identity matrix.
-                      (else #f))))
-        (cond
-         ((and (rect? region)
-               (not matrix)
-               (zero? rotation) ; no rotation
-               (= scale 1.0)) ; no scale
-          ;; We won't be using a transformation matrix.
-          ;; Just apply the offset.
-          (set-rect-x! rect (- (rect-x region) (vec2-x offset)))
-          (set-rect-y! rect (- (rect-y region) (vec2-y offset)))
-          (set-rect-width! rect (rect-width region))
-          (set-rect-height! rect (rect-height region)))
-         ((rect? region)
-          ;; We will be using a transformation matrix, so
-          ;; ignore the region's X and Y coordinates as
-          ;; those will be accounted for in the
-          ;; translation matrix.
-          (set-rect-x! rect (- (vec2-x offset)))
-          (set-rect-y! rect (- (vec2-y offset)))
-          (set-rect-width! rect (rect-width region))
-          (set-rect-height! rect (rect-height region)))
-         ((and (not matrix)
-               (zero? rotation)
-               (= scale 1.0))
-          ;; No region specified and no transformation
-          ;; matrix. Use texture width/height for the
-          ;; dimensions of the region.
-          (set-rect-x! rect (- (vec2-x region) (vec2-x offset)))
-          (set-rect-y! rect (- (vec2-y region) (vec2-y offset)))
-          (set-rect-width! rect (f32vector-ref size 0))
-          (set-rect-height! rect (f32vector-ref size 1)))
-         (else
-          ;; No region specified but we will be using a
-          ;; transformation matrix.
-          (set-rect-x! rect (- (vec2-x offset)))
-          (set-rect-y! rect (- (vec2-y offset)))
-          (set-rect-width! rect (f32vector-ref size 0))
-          (set-rect-height! rect (f32vector-ref size 1))))
-        (if *batch?*
-            (draw-sprite-batched texture rect matrix blend-mode
-                                 shader texcoords)
-            (draw-sprite-unbatched texture rect matrix blend-mode
-                                   shader texcoords))))))
+      (matrix4-2d-transform! matrix
+                             #:origin origin
+                             #:position position
+                             #:rotation rotation
+                             #:scale scale)
+      (draw-sprite* texture (texture-rect texture) matrix
+                    #:blend-mode blend-mode
+                    #:shader shader))))
 
 \f
 ;;;
 ;;; Nine Patches
 ;;;
 
-(define draw-nine-patch
-  (let ((rect (make-rect 0.0 0.0 0.0 0.0))
-        (trect (make-rect 0.0 0.0 0.0 0.0)))
-    (lambda* (texture region #:key (margin 0)
-                      (top-margin margin) (bottom-margin margin)
-                      (left-margin margin) (right-margin margin)
-                      (offset %default-offset)
-                      (rotation 0)
-                      (scale 1.0)
-                      matrix
-                      (blend-mode 'alpha)
-                      (shader (force default-shader)))
-      "Draw a \"nine patch\" sprite.  A nine patch sprite renders
-TEXTURE as a WIDTH x HEIGHT rectangle whose stretchable areas are
-defined by the given margin measurements.  The corners are never
-stretched, the left and right edges may be stretched vertically, the
-top and bottom edges may be stretched horizontally, and the center may
-be stretched in both directions.  This rendering technique is
-particularly well suited for resizable windows and buttons in
-graphical user interfaces.
-
-MARGIN specifies the margin size for all sides of the nine patch.  To
-make margins of differing sizes, the TOP-MARGIN, BOTTOM-MARGIN,
-LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
-      (let* ((texcoords (if (texture-region? texture)
-                            (texture-region-gl-rect texture)
-                            %default-texcoords))
-             (texsize (if (texture-region? texture)
-                          (texture-region-gl-size texture)
-                          (texture-gl-size texture)))
-             (w (rect-width region))
-             (h (rect-height region))
-             (border-x1 (rect-left region))
-             (border-y1 (rect-bottom region))
-             (border-x2 (rect-right region))
-             (border-y2 (rect-top region))
+(define draw-nine-patch*
+  (let ((%rect (make-rect 0.0 0.0 0.0 0.0))
+        (texcoords (make-rect 0.0 0.0 0.0 0.0)))
+    (lambda* (texture
+              rect
+              matrix
+              #:key
+              (margin 0.0)
+              (top-margin margin)
+              (bottom-margin margin)
+              (left-margin margin)
+              (right-margin margin)
+              (blend-mode 'alpha)
+              (shader (force default-shader)))
+      (let* ((x (rect-x rect))
+             (y (rect-y rect))
+             (w (rect-width rect))
+             (h (rect-height rect))
+             (border-x1 x)
+             (border-y1 y)
+             (border-x2 (+ x w))
+             (border-y2 (+ y h))
              (fill-x1 (+ border-x1 left-margin))
              (fill-y1 (+ border-y1 bottom-margin))
              (fill-x2 (- border-x2 right-margin))
              (fill-y2 (- border-y2 top-margin))
-             (tw (f32vector-ref texsize 0))
-             (th (f32vector-ref texsize 1))
-             (border-s1 (rect-left texcoords))
-             (border-t1 (rect-bottom texcoords))
-             (border-s2 (rect-right texcoords))
-             (border-t2 (rect-top texcoords))
+             (prect (texture-rect texture))
+             (trect (texture-gl-rect texture))
+             (tw (rect-width prect))
+             (th (rect-height prect))
+             (border-s1 (rect-left trect))
+             (border-t1 (rect-bottom trect))
+             (border-s2 (rect-right trect))
+             (border-t2 (rect-top trect))
              (fill-s1 (+ border-s1 (/ left-margin tw)))
              (fill-t1 (+ border-t1 (/ bottom-margin th)))
              (fill-s2 (- border-s2 (/ right-margin tw)))
              (fill-t2 (- border-t2 (/ top-margin th))))
         (define (draw-piece x1 y1 x2 y2 s1 t1 s2 t2)
-          (set-rect-x! rect x1)
-          (set-rect-y! rect y1)
-          (set-rect-width! rect (- x2 x1))
-          (set-rect-height! rect (- y2 y1))
-          (set-rect-x! trect s1)
-          (set-rect-y! trect t1)
-          (set-rect-width! trect (- s2 s1))
-          (set-rect-height! trect (- t2 t1))
-          (draw-sprite texture rect
-                       #:texcoords trect
-                       #:offset offset
-                       #:scale scale
-                       #:rotation rotation
-                       #:matrix matrix
-                       #:blend-mode blend-mode
-                       #:shader shader))
+          (set-rect-x! %rect x1)
+          (set-rect-y! %rect y1)
+          (set-rect-width! %rect (- x2 x1))
+          (set-rect-height! %rect (- y2 y1))
+          (set-rect-x! texcoords s1)
+          (set-rect-y! texcoords t1)
+          (set-rect-width! texcoords (- s2 s1))
+          (set-rect-height! texcoords (- t2 t1))
+          (draw-sprite* texture %rect matrix
+                        #:texcoords texcoords
+                        #:blend-mode blend-mode
+                        #:shader shader))
         (with-batched-sprites
          ;; bottom-left
          (draw-piece border-x1 border-y1 fill-x1 fill-y1
@@ -516,7 +435,7 @@ LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
          ;; bottom-center
          (draw-piece fill-x1 border-y1 fill-x2 fill-y1
                      fill-s1 border-t1 fill-s2 fill-t1)
-         ;; dbottom-right
+         ;; bottom-right
          (draw-piece fill-x2 border-y1 border-x2 fill-y1
                      fill-s2 border-t1 border-s2 fill-t1)
          ;; center-left
@@ -537,3 +456,49 @@ LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
          ;; top-right
          (draw-piece fill-x2 fill-y2 border-x2 border-y2
                      fill-s2 fill-t2 border-s2 border-t2))))))
+
+(define draw-nine-patch
+  (let ((position (vec2 0.0 0.0))
+        (%rect (make-rect 0.0 0.0 0.0 0.0))
+        (matrix (make-null-matrix4)))
+    (lambda* (texture
+              rect
+              #:key
+              (margin 0.0)
+              (top-margin margin) (bottom-margin margin)
+              (left-margin margin) (right-margin margin)
+              (origin %null-vec2)
+              (rotation 0.0)
+              (scale %default-scale)
+              (blend-mode 'alpha)
+              (shader (force default-shader)))
+      "Draw a \"nine patch\" sprite.  A nine patch sprite renders
+TEXTURE on the rectangular area RECT whose stretchable areas are
+defined by the given margin measurements.  The corners are never
+stretched, the left and right edges may be stretched vertically, the
+top and bottom edges may be stretched horizontally, and the center may
+be stretched in both directions.  This rendering technique is
+particularly well suited for resizable windows and buttons in
+graphical user interfaces.
+
+MARGIN specifies the margin size for all sides of the nine patch.  To
+make margins of differing sizes, the TOP-MARGIN, BOTTOM-MARGIN,
+LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
+      (set-rect-x! %rect 0.0)
+      (set-rect-y! %rect 0.0)
+      (set-rect-width! %rect (rect-width rect))
+      (set-rect-height! %rect (rect-height rect))
+      (set-vec2-x! position (rect-x rect))
+      (set-vec2-y! position (rect-y rect))
+      (matrix4-2d-transform! matrix
+                             #:origin origin
+                             #:position position
+                             #:rotation rotation
+                             #:scale scale)
+      (draw-nine-patch* texture %rect matrix
+                        #:top-margin top-margin
+                        #:bottom-margin bottom-margin
+                        #:left-margin left-margin
+                        #:right-margin right-margin
+                        #:blend-mode blend-mode
+                        #:shader shader))))
index 34be3fe..5c8ea7b 100644 (file)
   #:use-module (chickadee render gl)
   #:use-module (chickadee render gpu)
   #:export (make-texture
+            make-texture-region
             load-image
             texture?
+            texture-region?
             texture-null?
             texture-id
             texture-parent
-            texture-width
-            texture-height
             texture-min-filter
             texture-mag-filter
             texture-wrap-s
             texture-wrap-t
+            texture-rect
+            texture-gl-rect
             null-texture
             texture-set!
             texture-ref
 
-            make-texture-region
-            texture-region?
-            texture-region-texture
-            texture-region-x
-            texture-region-y
-            texture-region-width
-            texture-region-height
-
             texture-atlas
             list->texture-atlas
             split-texture
 ;; The <texture> object is a simple wrapper around an OpenGL texture
 ;; id.
 (define-record-type <texture>
-  (%make-texture id width height min-filter mag-filter wrap-s wrap-t gl-size)
+  (%make-texture id parent min-filter mag-filter wrap-s wrap-t rect gl-rect)
   texture?
   (id texture-id)
-  (width texture-width)
-  (height texture-height)
+  (parent texture-parent)
   (min-filter texture-min-filter)
   (mag-filter texture-mag-filter)
   (wrap-s texture-wrap-s)
   (wrap-t texture-wrap-t)
-  (gl-size texture-gl-size))
+  (rect texture-rect)
+  (gl-rect texture-gl-rect))
 
 (set-record-type-printer! <texture>
   (lambda (texture port)
     (format port
-            "#<texture width: ~d height: ~d min-filter: ~a mag-filter: ~a wrap-s: ~a wrap-t: ~a>"
-            (texture-width texture)
-            (texture-height texture)
+            "#<texture region?: ~a rect: ~a min-filter: ~a mag-filter: ~a wrap-s: ~a wrap-t: ~a>"
+            (texture-region? texture)
+            (texture-rect texture)
             (texture-min-filter texture)
             (texture-mag-filter texture)
             (texture-wrap-s texture)
             (texture-wrap-t texture))))
 
 (define null-texture
-  (%make-texture 0 0 0 'linear 'linear 'repeat 'repeat (f32vector 0.0 0.0)))
+  (%make-texture 0 #f 'linear 'linear 'repeat 'repeat
+                 (make-rect 0.0 0.0 0.0 0.0) (make-rect 0.0 0.0 0.0 0.0)))
 
 (define <<texture>> (class-of null-texture))
 
@@ -99,6 +94,9 @@
   "Return #t if TEXTURE is the null texture."
   (eq? texture null-texture))
 
+(define (texture-region? texture)
+  (texture? (texture-parent texture)))
+
 (define (free-texture texture)
   (gl-delete-texture (texture-id texture)))
 
@@ -150,9 +148,10 @@ clamp-to-edge.  FORMAT specifies the pixel format.  Currently only
       ('clamp-to-edge (texture-wrap-mode clamp-to-edge-sgis))))
 
   (let ((texture (gpu-guard
-                  (%make-texture (gl-generate-texture) width height
+                  (%make-texture (gl-generate-texture) #f
                                  min-filter mag-filter wrap-s wrap-t
-                                 (f32vector width height)))))
+                                 (make-rect 0.0 0.0 width height)
+                                 (make-rect 0.0 0.0 1.0 1.0)))))
     (texture-set! 0 texture)
     (gl-texture-parameter (texture-target texture-2d)
                           (texture-parameter-name texture-min-filter)
@@ -178,6 +177,26 @@ clamp-to-edge.  FORMAT specifies the pixel format.  Currently only
                          (or pixels %null-pointer))
     texture))
 
+(define (make-texture-region texture rect)
+  "Create a new texture region covering a section of TEXTURE defined
+by the bounding box RECT."
+  (let* ((parent-rect (texture-rect texture))
+         (pw (rect-width parent-rect))
+         (ph (rect-height parent-rect))
+         (x (rect-x rect))
+         (y (rect-y rect))
+         (w (rect-width rect))
+         (h (rect-height rect))
+         (gl-rect (make-rect (/ x pw) (/ y ph) (/ w pw) (/ h ph))))
+    (%make-texture (texture-id texture)
+                   texture
+                   (texture-min-filter texture)
+                   (texture-mag-filter texture)
+                   (texture-wrap-s texture)
+                   (texture-wrap-t texture)
+                   rect
+                   gl-rect)))
+
 (define (flip-pixels-vertically pixels width height)
   "Create a new bytevector that reverses the rows in PIXELS, a WIDTH x
 HEIGHT, 32 bit color bytevector."
@@ -227,33 +246,6 @@ magnification.  Valid values are 'nearest and 'linear.  By default,
 
 \f
 ;;;
-;;; Texture Regions
-;;;
-
-(define-record-type <texture-region>
-  (%make-texture-region texture x y width height gl-rect gl-size)
-  texture-region?
-  (texture texture-region-texture)
-  (x texture-region-x)
-  (y texture-region-y)
-  (width texture-region-width)
-  (height texture-region-height)
-  (gl-rect texture-region-gl-rect)
-  (gl-size texture-region-gl-size))
-
-(define (make-texture-region texture x y width height)
-  "Create a new texture region covering a section of TEXTURE defined
-by the bounding box X, Y, WIDTH, and HEIGHT.  All coordinates are
-measured in pixels and must be integers."
-  (let* ((tw (texture-width texture))
-         (th (texture-height texture))
-         (gl-rect (make-rect (/ x tw) (/ y th)
-                             (/ width tw) (/ height th))))
-    (%make-texture-region texture x y width height gl-rect
-                          (f32vector width height))))
-
-\f
-;;;
 ;;; Texture Atlas
 ;;;
 
@@ -272,7 +264,7 @@ coordinate rects denoting the various tiles within."
       (match rects
         (() (%make-texture-atlas texture v))
         (((x y width height) . rest)
-         (vector-set! v i (make-texture-region texture x y width height))
+         (vector-set! v i (make-texture-region texture (make-rect x y width height)))
          (loop (1+ i) rest))))))
 
 (define (texture-atlas texture . rects)
@@ -296,8 +288,9 @@ around its border.
 
 This type of texture atlas layout is very common for tile map
 terrain."
-  (let* ((w (texture-width texture))
-         (h (texture-height texture))
+  (let* ((r (texture-rect texture))
+         (w (rect-width r))
+         (h (rect-height r))
          (sw (/ tile-width w))
          (th (/ tile-height h))
          (rows (/ (- h margin) (+ tile-height spacing)))
@@ -306,7 +299,7 @@ terrain."
     (define (make-tile tx ty)
       (let* ((x (+ (* tx (+ tile-width spacing)) margin))
              (y (+ (* ty (+ tile-height spacing)) margin)))
-        (make-texture-region texture x y tile-width tile-height)))
+        (make-texture-region texture (make-rect x y tile-width tile-height))))
     (let y-loop ((y 0))
       (when (< y rows)
         (let x-loop ((x 0))
index cb3c885..e2864a5 100644 (file)
@@ -681,10 +681,26 @@ players, NPCs, items, particles, text, etc.  In Chickadee, bitmaps are
 stored in textures (@pxref{Textures}) and can be used to draw sprites
 via the @code{draw-sprite} procedure.
 
-@deffn {Procedure} draw-sprite @var{texture} @var{region} @
-       [#:scale] [#:rotation] [#:blend-mode alpha] [#:texcoords] @
-       [#:shader]
+@deffn {Procedure} draw-sprite @var{texture} @var{position} @
+       [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
+       [#:rect] [#:shader]
+
+Draw @var{texture} at @var{position}.
+
+Optionally, other transformations may be applied to the sprite.
+@var{rotation} specifies the angle to rotate the sprite, in radians.
+@var{scale} specifies the scaling factor as a 2D vector.  All
+transformations are applied relative to @var{origin}, a 2D vector,
+which defaults to the lower-left corner.
+
+Alpha blending is used by default but the blending method can be
+changed by specifying @var{blend-mode}.
+
+The area drawn to is as big as the texture, by default.  To draw to an
+arbitrary section of the screen, specify @var{rect}.
 
+Finally, advanced users may specify @var{shader} to change the way the
+sprite is rendered entirely.
 @end deffn
 
 It's not uncommon to need to draw hundreds or thousands of sprites
@@ -740,10 +756,10 @@ interface widgets like buttons and dialog boxes.  By using a nine
 patch, they can be rendered at any size without unappealing scaling
 artifacts.
 
-@deffn {Procedure} draw-nine-patch @var{texture} @var{region} @
+@deffn {Procedure} draw-nine-patch @var{texture} @var{rect} @
        [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
        [#:left-margin margin] [#:right-margin margin] @
-       [#:texture-region] [#:scale] [#:rotation] [#:blend-mode alpha] @
+       [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
        [#:shader]
 
 Draw a nine patch sprite.  A nine patch sprite renders @var{texture}
@@ -809,9 +825,7 @@ rendering technique comes in.  Introduced by
 @url{http://www.valvesoftware.com/.../2007/SIGGRAPH2007_AlphaTestedMagnification.pdf,
 Valve} in 2007, signed distance field fonts can be efficiently stored
 in a bitmap and be rendered at arbitrary scale factors with good
-results.  Chickadee can render both traditional bitmap fonts and
-signed distance field fonts.  @emph{Signed distance field font
-rendering is not yet available, so be patient.}
+results.
 
 While Chickadee does not yet offer a tool for converting TTF fonts
 into FNT fonts, tools such as
@@ -851,7 +865,7 @@ Return @code{#t} if @var{font} is an italicized font.
 @end deffn
 
 @deffn {Procedure} draw-text @var{font} @var{text} @var{position}
-       [#:scale] [#:rotation] [#:blend-mode]
+       [#:origin] [#:scale] [#:rotation] [#:blend-mode]
 
 Draw the string @var{text} with the first character starting at
 @var{position} using @var{font}.