-
Notifications
You must be signed in to change notification settings - Fork 24
Tutorial 7
Text is tricky. Not only is it tricky, it is common enough to make it seem like text is just a natural extension to any 2D library. Without tying to dissuade anyone, text involves problems such as kerning, spacing, fonts, languages, layout direction, alignment, points, and much, much more. Early computers simply used predefined blocks to create monospaced text. This works well, and is often desirable but good looking text is difficult. Good looking text in any language is almost impossible. This is why I included the Pango library in CLinch.
Pango simplifies text by using layouts, which are comparable to paragraphs. It's still a complex object to work with, so Pango created its own markup to help simplify things. CLinch allows easy access to this markup functionality through lispy-styled markup. Pango also includes a sister library which allows Cairo to be the renderer and perform Cairo operations, such as fill and stroke, on the text. This is a potent combination which allows for almost any conceivable text in out textures. This also means CLinch handles the details for converting between OpenGL, Cairo, Pango and XML. The result makes drawing text a treat rather than a chore.
We will again modify our previous tutorial. This time we need to add a few libraries to the top of the file.
(ql:quickload :clinch-pango)
(ql:quickload :alexandria)
CLinch-Pango is the sub-library which imports Pango, Pango-Cairo, and some useful CLinch utilities. Next, we don't need to pass draw function anything this time, so we'll simplify that. Also, in order to better read our text, we will will make the cube rotate on just the Y axis.
(when (zerop (mod frame-count 200))
(draw-on-texture))
(incf frame-count 1)
(clinch:set-identity-transform node)
(clinch:rotate node (clinch:degrees->radians (mod frame-count 360) ) 0 1 0)
Now we can modify the (draw-on-texture)
function. We will be using a circular list of lisp quotes (thank you Paul Graham's website) for our text, and we will cycle through one at a time and draw the top two. In order to do this we will use the (clinch:print-text ...
macro. This takes lispified XML and creates a layout object for it. The width parameter allows the layout to implement wrapping. Then we iterate through the list of quotes. The *print-circle*
just keeps your REPL from hanging if you peek at it.
(setf *print-circle* t)
(defvar quotes)
(defun draw-on-texture ()
(clinch:with-context-for-texture (texture01)
(clinch:clear-cairo-context)
(cairo:move-to (* 400 2/5) (* 400 1/10))
(cairo:scale 2 2)
(clinch:print-text `("span" (("font_desc" "Century Schoolbook L Roman 20"))
,(first quotes)) :width (* 400 3/5))
(clinch:print-text `("span" (("font_desc" "Century Schoolbook L Roman 20"))
,(second quotes)) :width (* 400 3/5)))
(setf quotes (cdr quotes)))
Finally at (init)
, we need to load our list quotes from a file. We'll use the Alexandria library to read input from the file and to create the circular list. It's a very useful library if you are not familiar with it you should make it a priority to learn.
(setf quotes
(apply #'alexandria:circular-list
(alexandria:with-input-from-file (s (concatenate 'string
(directory-namestring
(asdf:system-relative-pathname :clinch "clinch.asd"))
"examples/Tutorial07/quotes.txt"))
(loop for l = (read-line s nil nil)
while l collect l))))
Again, run (start)
to see the result. Be sure to sit through the entire list of quotes. Next time we will load a pre-existing mesh from an external data format using CLassimp.