@@ 63,17 63,18 @@
(defun blend (c1 c2)
(vec3* c1 c2))
-(defun create-canvas (width height)
- (make-array (list width height) :initial-element (vector 0 0 0)))
+(defstruct (canvas
+ (:constructor
+ make-canvas (&key width height)))
+ width
+ height
+ (body (make-array (list width height) :initial-element (vector 0 0 0))))
-(defun canvas-height (c)
- (nth 1 (array-dimensions c)))
-
-(defun canvas-width (c)
- (nth 0 (array-dimensions c)))
+;; (defun create-canvas (width height)
+;; (make-array (list width height) :initial-element (vector 0 0 0)))
(defun write-pixel (canvas x y color)
- (setf (aref canvas x y) color))
+ (setf (aref (canvas-body canvas) x y) color))
(defun wrap (text width)
(setq text (concatenate 'string text " "))
@@ 92,7 93,9 @@
(defun canvas-pixel-strings (c)
(labels ((pixel->string (v) (format nil "~s ~s ~s" (Red v) (Green v) (Blue v))))
- (loop for pixel across (make-array (apply #'* (array-dimensions c)) :displaced-to c)
+ (loop for pixel across
+ (make-array (apply #'* (array-dimensions (canvas-body c)))
+ :displaced-to (canvas-body c))
collect (pixel->string pixel))))
(defun canvas->string (c)
@@ 216,30 219,30 @@
(float= (BLUE blended-color) 0.04))))
(deftest canvas-properties
- (let* ((c (create-canvas 10 20))
+ (let* ((c (make-canvas :width 10 :height 20))
(w (canvas-width c))
(h (canvas-height c)))
(check (equalp w 10)
(equalp h 20)
- (loop for i across (make-array (* w h) :displaced-to c)
+ (loop for i across (make-array (* w h) :displaced-to (canvas-body c))
always (equalp i (vector 0 0 0))))))
(deftest canvas-write-pixel
- (let ((canvas (create-canvas 10 20))
+ (let ((canvas (make-canvas :width 10 :height 20))
(color (vector 1 0 0)))
(write-pixel canvas 2 3 color)
- (check (equalp (aref canvas 2 3) (vector 1 0 0)))))
+ (check (equalp (aref (canvas-body canvas) 2 3) (vector 1 0 0)))))
(deftest check-canvas-pixel-string
- (let ((c (create-canvas 1 2)))
+ (let ((c (make-canvas :width 1 :height 2)))
(check (equalp (canvas-pixel-strings c) (list "0 0 0" "0 0 0")))))
(deftest check-canvas-to-string
- (let ((c (create-canvas 1 2)))
+ (let ((c (make-canvas :width 1 :height 2)))
(check (equalp (canvas->string c) "0 0 0 0 0 0"))))
(deftest output-canvas-to-ppm
- (check (equalp (canvas->ppm (create-canvas 3 5))
+ (check (equalp (canvas->ppm (make-canvas :width 3 :height 5))
"P3
3 5
255
@@ 247,6 250,9 @@ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
")))
+(deftest ppm-includes-trailing-newline
+ (let ((c (canvas->ppm (make-canvas :width 3 :height 5))))
+ (check (equalp 0 (position #\Newline (reverse c) :test #'char=)))))
(deftest chapter-2
(color-vector-getters)
@@ 255,8 261,14 @@ 0 0 0 0 0 0 0 0 0 0
(canvas-write-pixel)
(check-canvas-pixel-string)
(check-canvas-to-string)
- (output-canvas-to-ppm))
+ (output-canvas-to-ppm)
+ (ppm-includes-trailing-newline))
+
+(defun ppm->file (ppm-string path)
+ (with-open-file (stream path :direction :output :if-exists :supersede)
+ (format stream ppm-string)))
(deftest suite
(chapter-1)
(chapter-2))
+