New module: src/rendering/framebuffer.lisp (tangled from org/framebuffer.org) - framebuffer-backend class: implements backend protocol by writing to 2D cell array instead of emitting escape sequences - cell struct: per-cell state (char, fg, bg, bold, italic, underline, link-url) - make-framebuffer / framebuffer-width / framebuffer-height - draw-text, draw-rect, draw-border, draw-link, draw-ellipsis methods - diff-framebuffers: compares two framebuffers, returns changed cells - flush-framebuffer: diff + output changes to real backend - with-scissor macro: clip drawing operations to rectangle - cursor-move: added default no-op method for all backends - 20 new tests, all passing (372 total) Version bumped from 0.11.0 to 0.13.0. License field set to GPL-3.0 in ASDF.
67 lines
2.5 KiB
Common Lisp
67 lines
2.5 KiB
Common Lisp
(defpackage :cl-tty-framebuffer-test
|
|
(:use :cl :fiveam :cl-tty.rendering :cl-tty.backend))
|
|
(in-package :cl-tty-framebuffer-test)
|
|
|
|
(def-suite framebuffer-suite :description "Framebuffer rendering pipeline tests")
|
|
(in-suite framebuffer-suite)
|
|
|
|
(test make-framebuffer-creates-correct-size
|
|
(let ((fb (make-framebuffer 80 24)))
|
|
(is (= 24 (framebuffer-height fb)))
|
|
(is (= 80 (framebuffer-width fb)))))
|
|
|
|
(test cell-defaults-are-space
|
|
(let ((cell (aref (make-framebuffer 10 10) 0 0)))
|
|
(is (eql #\space (cell-char cell)))
|
|
(is (null (cell-fg cell)))
|
|
(is (null (cell-bg cell)))))
|
|
|
|
(test draw-text-on-fb-sets-cells
|
|
(let ((fb (make-framebuffer-backend)))
|
|
(draw-text fb 2 3 "abc" :red nil)
|
|
(let ((cells (fb-framebuffer fb)))
|
|
(is (eql #\a (cell-char (aref cells 3 2))))
|
|
(is (eql #\b (cell-char (aref cells 3 3))))
|
|
(is (eql #\c (cell-char (aref cells 3 4))))
|
|
(is (eql :red (cell-fg (aref cells 3 2)))))))
|
|
|
|
(test draw-text-clips-at-bounds
|
|
(let ((fb (make-framebuffer-backend :width 10 :height 5)))
|
|
(draw-text fb 8 2 "hello" nil nil)
|
|
(let ((cells (fb-framebuffer fb)))
|
|
(is (eql #\h (cell-char (aref cells 2 8))))
|
|
(is (eql #\e (cell-char (aref cells 2 9))))
|
|
(is (eql #\space (cell-char (aref cells 2 0))) "out of bounds text is ignored"))))
|
|
|
|
(test diff-identical-fbs-returns-empty
|
|
(let ((fb1 (make-framebuffer 80 24))
|
|
(fb2 (make-framebuffer 80 24)))
|
|
(is (null (diff-framebuffers fb1 fb2)))))
|
|
|
|
(test diff-changed-fb-returns-changes
|
|
(let* ((fb1 (make-framebuffer 10 10))
|
|
(fb2 (make-framebuffer 10 10)))
|
|
(setf (aref fb2 5 5) (make-cell :char #\X :fg :red))
|
|
(let ((changes (diff-framebuffers fb1 fb2)))
|
|
(is (= 1 (length changes)))
|
|
(destructuring-bind (x y cell) (first changes)
|
|
(is (= 5 x))
|
|
(is (= 5 y))
|
|
(is (eql #\X (cell-char cell)))))))
|
|
|
|
(test with-scissor-clips-drawing
|
|
(let ((fb (make-framebuffer-backend :width 20 :height 10)))
|
|
(with-scissor (fb 5 5 3 3)
|
|
(draw-text fb 6 6 "ABC" nil nil)
|
|
(draw-text fb 1 1 "OUTSIDE" nil nil))
|
|
(let ((cells (fb-framebuffer fb)))
|
|
(is (eql #\A (cell-char (aref cells 6 6))) "inside scissor draws")
|
|
(is (eql #\space (cell-char (aref cells 1 1))) "outside scissor is clipped"))))
|
|
|
|
(test flush-fb-copies-to-backend
|
|
(let* ((real-be (make-simple-backend :output-stream (make-string-output-stream)))
|
|
(fb (make-framebuffer-backend)))
|
|
(draw-text fb 0 0 "X" :red nil)
|
|
(let ((changed (flush-framebuffer (make-framebuffer 80 24) (fb-framebuffer fb) real-be)))
|
|
(is (>= changed 1)))))
|