<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nklein software &#187; woolly</title>
	<atom:link href="http://nklein.com/tags/woolly/feed/" rel="self" type="application/rss+xml" />
	<link>http://nklein.com</link>
	<description>software development and consulting</description>
	<lastBuildDate>Thu, 22 Dec 2011 04:42:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Woolly Application Underway</title>
		<link>http://nklein.com/2009/12/woolly-application-underway/</link>
		<comments>http://nklein.com/2009/12/woolly-application-underway/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 00:36:55 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1062</guid>
		<description><![CDATA[I started building an application on top my Sheeple/CL-OpenGL library Woolly. I coach a volleyball team. I often sit down with a piece of paper and try to determine new serve-receive and defensive positions for my team. This is quite tedious because I can&#8217;t just move the players around on the page. Additionall, I have [...]]]></description>
			<content:encoded><![CDATA[<p>I started building an application on top my Sheeple/CL-OpenGL library <a href="http://nklein.com/software/woolly/">Woolly</a>.</p>
<p>I <a href="http://mnvolleyballhq.com/">coach a volleyball team</a>.  I often sit down with a piece of paper and try to determine new serve-receive and defensive positions for my team.  This is quite tedious because I can&#8217;t just move the players around on the page.  Additionall, I have to figure this out for all six rotations while keeping the overlap requirements in mind the whole time.</p>
<p>I tried once doing it with cut-out players.  This worked better, but still suffered from having to track the rotations and overlap requirements all myself.</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/12/rotations.png"><img src="http://nklein.com/wp-content/uploads/2009/12/rotations-300x235.png" alt="rotations" title="rotations" width="300" height="235" class="alignright size-medium wp-image-1063" /></a> After adding checkboxes to Woolly, I had a usable application for doing these rotations in 300 lines of code.  Yellow are front-row players, blue are back-row players, and green are sidelined players.  It still needs some work so that I can change player identifiers, substitute players in off the bench, save/load the rotations, and make print-outs.</p>
<p>I&#8217;m not sure yet whether I&#8217;m going to print just by slurping the OpenGL buffer into ZPNG, or if I am going to make a separate callback hierarchy for printing with Vecto or CL-PDF so that I can print at higher than screen resolution.</p>
<p>I&#8217;m also having trouble getting SBCL&#8217;s <b>save-lisp-and-die</b> function happy with the whole CL-OpenGL setup under MacOSX.  I thought I had figured this out before.  Alas, my own hacked version of CL-OpenGL isn&#8217;t working any better for me than the current CL-OpenGL release is when I try to run the saved image.  *shrug*  I&#8217;ll fight with that later.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/woolly-application-underway/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rendering Text in CL-OpenGL with ZPB-TTF</title>
		<link>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/</link>
		<comments>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 01:24:02 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1051</guid>
		<description><![CDATA[I promised in an earlier post that I would share my code for rendering anti-aliased text in CL-OpenGL using ZPB-TTF to load the fonts. Overview I use a three step process to render a string. First, I render the outline of the string using anti-alised lines. Then, I render the string as solid polygons into [...]]]></description>
			<content:encoded><![CDATA[<p>I promised in <a href="http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/">an earlier post</a> that I would share my code for rendering anti-aliased text in <a href="http://common-lisp.net/project/cl-opengl/">CL-OpenGL</a> using <a href="http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF</a> to load the fonts.</p>
<h3>Overview</h3>
<p>I use a three step process to render a string.  First, I render the outline of the string using anti-alised lines.  Then, I render the string as solid polygons into the stencil buffer.  Then, I fill a rectangle having OpenGL only fill where the stencil buffer is set.</p>
<p>Why the three-step process?  OpenGL can draw polygons.  In fact, it can draw anti-aliased polygons.  However, it can only draw convex polygons.  Most of the polygons involved in fonts are non-convex.  The stencil buffer, however, has a drawing mode where you can flip the bits of the value in the stencil buffer each time OpenGL goes to write to it.</p>
<p>Imagine for a moment the letter <q>O</q>.  It is made of two separate contours&#8230; one for the exterior of the circle and one for the interior of the circle.  If I rendered each of these to the color buffer in OpenGL, I would end up with one big filled in circle.  However, if I render each of these to the stencil buffer with the invert operation, then I end up setting all of the bits in the filled circle area when I draw the exterior contour and turning the middle bits off again when I render the internal contour.  I am left with only the bits in the letter itself filled in.</p>
<p>The same sort of thing works even for more complicated letters like the letter <q>C</q>.  As I am progressing along the outer edge, I am inadvertently filling the interior region. But, as I progress along the inner edge, I am inadvertently erasing that region again.</p>
<p>Once I am done, I use the stencil buffer as a stencil, draw a rectangle over it, and Bob&#8217;s your uncle.</p>
<p>The problem with the stencil buffer is that it has no subtlety.  Bits are either set in it or not.  So, I cannot anti-alias in the stencil buffer.  I am left to draw the outline with anti-aliased lines.</p>
<p>Here are the relevant files:</p>
<ul>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/draw.lisp">draw.lisp</a>: The code which actually draws strings in a given font.</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/gl.lisp">gl.lisp</a>:  The code that makes a basic OpenGL window and invokes the font rendering on a given font and string.</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/test.lisp">test.lisp</a>:  Some simple code that loads the required libraries and opens a window.</li>
</ul>
<p>The test program assumes that <q>okolaksRegular.ttf</q> is in your current directory.  Tweak it to some TTF you do have.  Or, get <a href="http://openfontlibrary.org/media/files/gluk/240">Okolaks</a> itself.</p>
<h3>Drawing a string</h3>
<p>Here is the basic outline of the string drawing function.  I am centering the string at the origin.  I first calculate the bounding box.  Then, I determine the scaling factor needed to get from the font-units into my own units and I scale the universe accordingly.  Then, I translate the universe to center the bounding box.  Then, I draw the anti-aliased outline of the text.  If desired, I then draw the filled text to the stencil buffer and paint in the stencil.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> draw-string <span style="color: #66cc66;">&#40;</span>font-loader string <span style="color: #66cc66;">&amp;</span>key <span style="color: #66cc66;">&#40;</span>size <span style="color: #cc66cc;">48</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>filled t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span>* <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>box <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">string-bounding-box</span> string font-loader <span style="color: #66cc66;">:</span><span style="color: #555;">kerning</span> t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>bx1 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>by1 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>bx2 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>by2 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
      <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>ss <span style="color: #66cc66;">&#40;</span>/ size <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">units</span>/em font-loader<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">scale</span> ss ss <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
      <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>- bx1 bx2<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>- by1 by2<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
      <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-attrib</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">current-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">color-buffer-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-bit</span>
                                           <span style="color: #66cc66;">:</span><span style="color: #555;">hint-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-buffer-bit</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&lt;&lt;</span>draw antialiased lines<span style="color: #66cc66;">&gt;&gt;</span>
      <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> filled
        <span style="color: #66cc66;">&lt;&lt;</span>fill stencil buffer with filled-in-glyph<span style="color: #66cc66;">&gt;&gt;</span>
        <span style="color: #66cc66;">&lt;&lt;</span>fill in area subject to stencil<span style="color: #66cc66;">&gt;&gt;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>To <q>draw antialiased lines</q>, I turn on blending.  I tell it to blend the color in according to the alpha value of the portion of line it is trying to draw.  I tell it to draw smooth lines in the nicest way it knows how.  Then, I save the transformation-state so that I can move around inside the actual string rendering and still get back to this exact same place later.  When I am done, I no longer need blending.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">blend</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">blend-func</span> <span style="color: #66cc66;">:</span><span style="color: #555;">src-alpha</span> <span style="color: #66cc66;">:</span><span style="color: #555;">one-minus-src-alpha</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-smooth</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">hint</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-smooth-hint</span> <span style="color: #66cc66;">:</span><span style="color: #555;">nicest</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span>
    <span style="color: #66cc66;">&#40;</span>render-string string font-loader <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>To <q>fill stencil buffer with filled-in-glyph</q>, I turn off writing to the color buffer.  I turn on the stencil testing.  I set myself up to use a 1-bit stencil buffer.  I set the buffer up so that when I clear it, it will all be zero-ed.  I clear the stencil buffer.  I set the stencil test to always write one bit.  And, I set the stencil buffer to always write in <q>invert</q> mode.  Then, I draw the string filled.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">color-mask</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-test</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-mask</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">clear-stencil</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">clear</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-buffer-bit</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-func</span> <span style="color: #66cc66;">:</span><span style="color: #555;">always</span> <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-op</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span>
    <span style="color: #66cc66;">&#40;</span>render-string string font-loader t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>To <q>fill in area subject to stencil</q>, I set myself up again to write to the color buffer.  I set up the stencil test to let me write to my buffers only where the stencil is set to one.  Then, I draw a filled rectangle over the whole bounding box.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">color-mask</span> t t t t<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-func</span> <span style="color: #66cc66;">:</span><span style="color: #b1b100;">equal</span> <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-primitives</span> <span style="color: #66cc66;">:</span><span style="color: #555;">quads</span>
  <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx1 by1<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx2 by1<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx2 by2<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx1 by2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<h3>Rendering the string</h3>
<p>To render the string, I loop through each character in it.  For characters other than the first one, I adjust their position based on the kerning offset.  Then, I render the character glyph and adjust the position so that I am ready to start the next character.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> render-string <span style="color: #66cc66;">&#40;</span>string font-loader fill<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>loop <span style="color: #66cc66;">:</span><span style="color: #555;">for</span> pos <span style="color: #66cc66;">:</span><span style="color: #555;">from</span> <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">:</span><span style="color: #555;">below</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">length</span> string<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">:</span><span style="color: #555;">for</span> cur <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">find-glyph</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> string pos<span style="color: #66cc66;">&#41;</span> font-loader<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">:</span><span style="color: #555;">for</span> prev <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">nil</span> <span style="color: #66cc66;">:</span><span style="color: #555;">then</span> cur
     <span style="color: #66cc66;">:</span><span style="color: #b1b100;">do</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> prev
           <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>- <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">kerning-offset</span> prev cur font-loader<span style="color: #66cc66;">&#41;</span>
                            <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">left-side-bearing</span> cur<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                         <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
         <span style="color: #66cc66;">&#40;</span>render-glyph cur <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> fill <span style="color: #66cc66;">:</span><span style="color: #555;">polygon</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-strip</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
         <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">advance-width</span> cur<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<h3>Rendering a glyph</h3>
<p>Here&#8217;s where the rubber really meets the road.  My <q>render-glyph</q> function takes two arguments: a glyph and the mode in which to render it.  The mode is <q>:polygon</q> for filled polygons and <q>:line-strip</q> for just the outline.</p>
<p>I loop through each contour in the glyph.  With each contour, I tell OpenGL that I am going to render either a single polygon or a single line strip (according to the mode).  To render the contour then, I loop through each contour segment.  Each contour segment is either a straight line or a quadratic spline.  If it is a straight line, then I have it easy.  I just have to render the end points.  If it is a spline, I have to render the starting point, create some interpolators to interpolate points along the spline, use those interpolators, and then render the end point.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> render-glyph <span style="color: #66cc66;">&#40;</span>glyph mode<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">do-contours</span> <span style="color: #66cc66;">&#40;</span>contour glyph<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-primitives</span> mode
      <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">do-contour-segments</span> <span style="color: #66cc66;">&#40;</span>start ctrl end<span style="color: #66cc66;">&#41;</span> contour
        <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>sx <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> start<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>sy <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> start<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>cx <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> ctrl<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>cy <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> ctrl<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>ex <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> end<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>ey <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> end<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> sx sy<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl
            <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>int-x <span style="color: #66cc66;">&#40;</span>make-interpolator sx cx ex<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                  <span style="color: #66cc66;">&#40;</span>int-y <span style="color: #66cc66;">&#40;</span>make-interpolator sy cy ey<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span>interpolate sx sy ex ey int-x int-y<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> ex ey<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>The starting point of one contour segment is always the ending point of the previous contour segment.  So, if I wanted to bother, I could save myself a few OpenGL calls by remembering the first starting point of the first segment of the contour, not rendering the end points of any contour segment, and then rendering the starting point of the first segment again at the end (when I&#8217;m in outline mode).  Instead, for clarity, I just always render the end point.</p>
<h3>Making spline interpolators</h3>
<p>If I want to make an quadratic spline that goes from <img src="http://l.wordpress.com/latex.php?latex=x_0&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="x_0" style="vertical-align:-20%;" class="tex" alt="x_0" /> to <img src="http://l.wordpress.com/latex.php?latex=x_1&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="x_1" style="vertical-align:-20%;" class="tex" alt="x_1" /> with control point <img src="http://nklein.com/wp-content/plugins/easy-latex/cache/tex_08c1898a88651cdd0a9fdb2d6ce6e8a1.png" title="c" style="vertical-align:-20%;" class="tex" alt="c" /> as time <img src="http://nklein.com/wp-content/plugins/easy-latex/cache/tex_4e156c4dfd6f5bd0adffc493c64bc7ca.png" title="t" style="vertical-align:-20%;" class="tex" alt="t" /> goes from zero to one, I would use the polynomial <img src="http://l.wordpress.com/latex.php?latex=%28x_0%20-%202c%20%2B%20x_1%29%20t%5E2%20%2B%202%28%20c%20-%20x_0%20%29%20t%20%2B%20x_0&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(x_0 - 2c + x_1) t^2 + 2( c - x_0 ) t + x_0" style="vertical-align:-20%;" class="tex" alt="(x_0 - 2c + x_1) t^2 + 2( c - x_0 ) t + x_0" />.  So, given the parameters of a contour segment, I&#8217;m going to create interpolators for the x and y coordinates independently like so:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> make-interpolator <span style="color: #66cc66;">&#40;</span>ss cc ee<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>xx <span style="color: #66cc66;">&#40;</span>+ ss <span style="color: #66cc66;">&#40;</span>* -<span style="color: #cc66cc;">2</span> cc<span style="color: #66cc66;">&#41;</span> ee<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>yy <span style="color: #66cc66;">&#40;</span>* <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">&#40;</span>- cc ss<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>zz ss<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    #'<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>tt<span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>+ <span style="color: #66cc66;">&#40;</span>* xx tt tt<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* yy tt<span style="color: #66cc66;">&#41;</span> zz<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<h3>Interpolating the spline</h3>
<p>To interpolate the spline, I use a recursive function.  It is given the x and y coordinates of the starting and ending points for the current portion of the spline, the starting and ending time coordinates of the current portion of the spline, and the interpolators created above.  From there, it calculates the midpoint of a line segment from the start to the end and the x and y coordinates that the midpoint should be at based on the spline interpolator functions.  If the calculated spline midpoint is really close to the line-segment midpoint, we just break off the recursion.  If it is not really close, then we interpolate the first half of the current portion, render the calculated spline portion midpoint, and interpolate the second half of the current portion.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> interpolate <span style="color: #66cc66;">&#40;</span>sx sy ex ey int-x int-y <span style="color: #66cc66;">&amp;</span>optional <span style="color: #66cc66;">&#40;</span>st <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>et <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>mx <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sx ex<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2.0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>my <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sy ey<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2.0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>mt <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ st et<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2.0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>nx <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-x mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>ny <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-y mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>dx <span style="color: #66cc66;">&#40;</span>- mx nx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#40;</span>dy <span style="color: #66cc66;">&#40;</span>- my ny<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#40;</span>+ <span style="color: #66cc66;">&#40;</span>* dx dx<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* dy dy<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>interpolate sx sy nx ny int-x int-y st mt<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> nx ny<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>interpolate nx ny ex ey int-x int-y mt et<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>Technically, that check with the squared distance from the calculated midpoint to the segment midpoint shouldn&#8217;t just compare against the number one.  It should be dynamic based on the current OpenGL transformation.  I should project the origin and the points <img src="http://l.wordpress.com/latex.php?latex=%281%2C0%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(1,0)" style="vertical-align:-20%;" class="tex" alt="(1,0)" /> and <img src="http://nklein.com/wp-content/plugins/easy-latex/cache/tex_899c0ad792ee5fca9071f5bbeb6fc9ad.png" title="(0,1)" style="vertical-align:-20%;" class="tex" alt="(0,1)" /> through the current OpenGL projections, then use the reciprocal of the maximum distance those projected points are from the projected origin in place of the one.  Right now, I am probably rendering many vertexes inside each screen pixel.</p>
<h3>Summary</h3>
<p>So, there you have it.  Should you ever need to render text in CL-OpenGL, I hope this saves you many hours of trial-and-error and keeps you from resorting to rendering the glyphs to a texture map and dealing with how poorly they scale.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>GUI Discussion &#8212; TC Lispers November Meeting</title>
		<link>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/</link>
		<comments>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 12:05:41 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[user interface toolkits]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1045</guid>
		<description><![CDATA[Cross-posted from TCLispers.org: Lisp GUI Discussion on Vimeo. Robert Goldman, Paul Krueger, and Patrick Stein gave short presentations on different approaches to Graphical User Interfaces with Common Lisp. Lisp GUIs or &#8220;Bloodied but Unbowed&#8221; by Robert Goldman CCL/Cocoa Interface by Paul Krueger GUIs with CL-OpenGL by Patrick Stein]]></description>
			<content:encoded><![CDATA[<p><em>Cross-posted from <a href="http://tclispers.org/">TCLispers.org</a>:</em></p>
<p><object width="640" height="480"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=7933728&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="640" height="480" src="http://vimeo.com/moogaloop.swf?clip_id=7933728&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><a href="http://vimeo.com/7933728">Lisp GUI Discussion</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Robert Goldman, Paul Krueger, and Patrick Stein gave short presentations on different approaches to Graphical User Interfaces with Common Lisp.</p>
<ul>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/lisp-guis.pdf">Lisp GUIs or &#8220;Bloodied but Unbowed&#8221;</a> by <a href="http://rpgoldman.real-time.com/">Robert Goldman</a></li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/TCL-Slides-Nov-2009.pdf">CCL/Cocoa Interface</a> by Paul Krueger</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/CL-OpenGL-GUI.pdf">GUIs with CL-OpenGL</a> by <a href="http://nklein.com/">Patrick Stein</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Development</title>
		<link>http://nklein.com/2009/11/cross-platform-development/</link>
		<comments>http://nklein.com/2009/11/cross-platform-development/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 01:31:04 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[vmware]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1018</guid>
		<description><![CDATA[In preparation for the upcoming TC Lispers meeting, I was testing my Sheeple-based CL-OpenGL GUI code on all of the different systems that I use. This was important because part of my goal in starting from bare-bones OpenGL was to make something that was pretty easy to port. The OpenGL libraries are the only non-Lisp [...]]]></description>
			<content:encoded><![CDATA[<p>In preparation for the <a href="http://tclispers.org/events/november-meeting">upcoming TC Lispers meeting</a>, I was testing my <a href="http://sykosomatic.org/sheeple/">Sheeple</a>-based <a href="http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/">CL-OpenGL GUI</a> code on all of the different systems that I use.  This was important because part of my goal in starting from bare-bones OpenGL was to make something that was pretty easy to port.  The OpenGL libraries are the only non-Lisp dependencies, and they are pretty standard.</p>
<p>I run Mac OS X 10.6.2 as my primary development machine.  I knew everything I had so far worked there under SBCL 1.0.30 and CMU-CL 20a.  It took a little tweaking to get Sheeple built under Allegro CL 8.1 (Trial Edition), but after that I was five-by-five under Allegro, too.  Unfortunately, I cannot get CL-OpenGL to run under Clozure 1.3-r11936 on Mac OS X.  Also, ECL 9.10.2 doesn&#8217;t support weak key hashtables which Sheeple needs.  And, my install of clisp broke somewhere along the lines, so I haven&#8217;t tried it.</p>
<p>I have an Ubuntu Linux box.  There, I am using SBCL 1.0.11.debian (eeps).  Everything ran perfectly over there (even displaying through X Windows back to my Mac).</p>
<p>I also run Windows Vista under VMWare Fusion on my Mac.  I hadn&#8217;t done any development on it for months and months.  Fortunately, in Google-ing to find out how to fix it, I stumbled upon <a href="http://nklein.com/2009/05/emacs-slime-sbcl-on-windows-vista/">what I had written about how I got things set up originally</a>.  Over the last two hours, I got SBCL upgraded to 1.0.29 under Vista.  I got ASDF-Install set up with a bunch of help from <a href="http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html">this article</a>.  And, from there, I got CFFI and cl-opengl and ZPB-TTF and Sheeple installed.</p>
<p>ZPB-TTF and Sheeple both used some tar format options that <a href="http://www.method-combination.net/blog/archives/2007/04/30/new-archive-release.html">archive_0.7.0</a> didn&#8217;t like.  For those, I had to jump through some hoops to untar and retar them to get them to install.</p>
<p>Here was my final <b>/Users/Patrick/.sbclrc</b> file:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>require <span style="color: #66cc66;">:</span><span style="color: #555;">asdf</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; from Zach Beane</span>
<span style="color: #66cc66;">&#40;</span>defmethod asdf<span style="color: #66cc66;">:</span><span style="color: #555;">perform</span> <span style="color: #66cc66;">:</span><span style="color: #555;">around</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>o asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span><span style="color: #66cc66;">&#41;</span>
                                <span style="color: #66cc66;">&#40;</span>c asdf<span style="color: #66cc66;">:</span><span style="color: #555;">cl-source-file</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>handler-<span style="color: #b1b100;">case</span> <span style="color: #66cc66;">&#40;</span>call-next-method o c<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span>#+sbcl sb-ext<span style="color: #66cc66;">:</span><span style="color: #555;">invalid-fasl</span>
     #+allegro excl<span style="color: #66cc66;">::</span><span style="color: #555;">file-incompatible-fasl-</span><span style="color: #b1b100;">error</span>
     #+lispworks conditions<span style="color: #66cc66;">:</span><span style="color: #555;">fasl-</span><span style="color: #b1b100;">error</span>
     #+cmu ext<span style="color: #66cc66;">:</span><span style="color: #555;">invalid-fasl</span>
     #-<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">or</span> sbcl allegor lispworks cmu<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">error</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">perform</span> <span style="color: #66cc66;">&#40;</span>make-instance 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">compile-op</span><span style="color: #66cc66;">&#41;</span> c<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span>call-next-method<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">dolist</span> <span style="color: #66cc66;">&#40;</span>pkg  '<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;alexandria/&quot;</span>
                <span style="color: #ff0000;">&quot;archive_0.7.0/&quot;</span>
                <span style="color: #ff0000;">&quot;asdf-install/asdf-install/&quot;</span>
                <span style="color: #ff0000;">&quot;babel_0.3.0/&quot;</span>
                <span style="color: #ff0000;">&quot;cffi_0.10.5/&quot;</span>
                <span style="color: #ff0000;">&quot;cl-opengl/&quot;</span>
                <span style="color: #ff0000;">&quot;flexi-streams-1.0.7/&quot;</span>
                <span style="color: #ff0000;">&quot;gzip-stream_0.2.8/&quot;</span>
                <span style="color: #ff0000;">&quot;salza2-2.0.7/&quot;</span>
                <span style="color: #ff0000;">&quot;sykopomp-sheeple-ceab213/&quot;</span>
                <span style="color: #ff0000;">&quot;trivial-features_0.6/&quot;</span>
                <span style="color: #ff0000;">&quot;trivial-gray-streams-2008-11-02/&quot;</span>
                <span style="color: #ff0000;">&quot;woolly/&quot;</span>
                <span style="color: #ff0000;">&quot;zpb-ttf-1.0/&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>pushnew <span style="color: #66cc66;">&#40;</span>merge-pathnames pkg
                            <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span>
                                             <span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
           asdf<span style="color: #66cc66;">:</span>*central-registry*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'asdf-install<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; for my sanity</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> asdf-install<span style="color: #66cc66;">:</span>*locations*
      <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">list</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">list</span> <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span> <span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                  <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span> <span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                  <span style="color: #ff0000;">&quot;My install spot&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; via http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html</span>
#+win32
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'gzip-stream<span style="color: #66cc66;">&#41;</span>
&nbsp;
#+win32
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'archive<span style="color: #66cc66;">&#41;</span>
&nbsp;
#+win32
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> asdf-install-extractor <span style="color: #66cc66;">&#40;</span>to-dir tarball<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">name</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span>gzip-stream<span style="color: #66cc66;">:</span><span style="color: #555;">with-open-gzip-file</span> <span style="color: #66cc66;">&#40;</span>ins tarball<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">with-open-archive</span> <span style="color: #66cc66;">&#40;</span>archive ins<span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>*default-pathname-defaults* <span style="color: #66cc66;">&#40;</span>pathname to-dir<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
	  <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">do-archive-entries</span> <span style="color: #66cc66;">&#40;</span>entry archive <span style="color: #b1b100;">name</span><span style="color: #66cc66;">&#41;</span>
	    <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">extract-entry</span> archive entry<span style="color: #66cc66;">&#41;</span>
	    <span style="color: #66cc66;">&#40;</span>unless <span style="color: #b1b100;">name</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> <span style="color: #b1b100;">name</span> <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> entry<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span>string <span style="color: #b1b100;">name</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
#+win32
<span style="color: #66cc66;">&#40;</span>push 'asdf-install-extractor asdf-install<span style="color: #66cc66;">:</span>*tar-extractors*<span style="color: #66cc66;">&#41;</span></pre></div>
<p>The list of packages in the middle were about half installed manually to get the archive extraction code working and half installed through ASDF-Install.  If I recall correctly, I had to manually install: <b>archive_0.7.0</b>, <b>flexi-streams-1.0.7</b>, <b>gzip-stream_0.2.8</b>, <b>salza2-2.0.7</b>, <b>trivial-gray-streams-2008-11-02</b>, and a fresh copy of <b>asdf-install</b>.  I also had to download a compiled version of <b>freeglut.dll</b> and tuck it into my Windows\system32 directory.</p>
<p>Getting SBCL to use the fresh copy of <b>asdf-install</b> was annoying.  I ended up starting up a Command Prompt as Administrator (right click on the &#8220;command.exe&#8221; icon or menu-item and select &#8220;Run as Administrator&#8221;).  Then, I went to the SBCL directory (&#8220;C:\Program Files\Steel Bank Common Lisp\1.0.29\&#8221;) and did the following:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><pre class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">%</span> rename asdf-install asdf-install.old
<span style="color: #000000; font-weight: bold;">%</span> mklink <span style="color: #000000; font-weight: bold;">/</span>d asdf-install <span style="color: #ff0000;">&quot;C:\Users\Patrick\ASDF-Systems\asdf-install\asdf-install<span style="color: #000099; font-weight: bold;">\&quot;</span></span></pre></div>
<p>I had extracted the tar-ball from the ASDF-Install distribution into my ASDF-Systems directory.</p>
<p>Then, I went back and made my GUI code use double-buffered OpenGL windows because running Lisp to OpenGL to Windows Vista to VMWare to Quartz had some wicked flickering going on.</p>
<p>Two hours is a long time for something that&#8217;s supposed to be <q>easily portable</q>.  But, I would have spent at least 95% of that time even if I were using an all-Lisp solution.  And, this is far less time than I ever spent porting anything else to Windows.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/11/cross-platform-development/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Playing with Sheeple-based GUI atop CL-OpenGL</title>
		<link>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/</link>
		<comments>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 16:59:55 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1007</guid>
		<description><![CDATA[Inspired by the previous TC Lispers meeting and spurred on by the probable topic of the next TC Lispers meeting, I have spent the little bit of coding time I&#8217;ve had over the past two weeks on making a GUI layer using Sheeple atop CL-OpenGL and employing ZPB-TTF for font-loading. I have dubbed this project [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by the <a href="http://tclispers.org/news/sheeple-presentation">previous TC Lispers meeting</a> and spurred on by the <a href="http://tclispers.org/should-we-discuss-question-cl-and-uis-november-meeting">probable topic of the next TC Lispers meeting</a>, I have spent the little bit of coding time I&#8217;ve had over the past two weeks on making a GUI layer using <a href="http://sykosomatic.org/sheeple/">Sheeple</a> atop <a href="http://common-lisp.net/project/cl-opengl/">CL-OpenGL</a> and employing <a href="http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF</a> for font-loading.</p>
<p>I have dubbed this project <q>Woolly</q> (because it&#8217;s made from Sheeple and because <q>Woolly</q> sounds sorta like <q>GUI</q>).</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/11/woolly-peek.png"><img src="http://nklein.com/wp-content/uploads/2009/11/woolly-peek-300x235.png" alt="woolly-peek" title="woolly-peek" width="300" height="235" class="alignright size-medium wp-image-1008" /></a>I spent about half of my coding time so far getting the basic framework in place (proven through clickable buttons with labels).  I am trying to keep it cleanly separated between generic GUI stuff and the CL-OpenGL specifics in the event that someone would like to port it to some other I/O spec.</p>
<p>The other half of my coding time was spent getting the font-rendering to be anti-aliased.  I promise to write more about how I accomplished the font-rendering in a future post so that if you&#8217;re ever stuck rendering fonts in OpenGL, you won&#8217;t be stuck with pixelated blockiness or resorting to rendering to a texture-map and letting the mipmapper figure it out.</p>
<p>For this post, however, I&#8217;ll just show you the code that sets up the interface depicted here.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><pre class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>require <span style="color: #66cc66;">:</span><span style="color: #555;">asdf</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">operate</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'woolly-gl <span style="color: #66cc66;">:</span><span style="color: #555;">verbose</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; make it easier to change renderer/controller later</span>
<span style="color: #66cc66;">&#40;</span>rename-package 'woolly-gl 'toolkit<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> test <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>font <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>font<span style="color: #66cc66;">=</span>
                              <span style="color: #66cc66;">:</span><span style="color: #555;">em-size</span> <span style="color: #cc66cc;">48</span>
                              <span style="color: #66cc66;">:</span><span style="color: #555;">pathname</span> <span style="color: #ff0000;">&quot;okolaks/okolaksRegular.ttf&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>app <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>app<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>win <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>window<span style="color: #66cc66;">=</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">title</span> <span style="color: #ff0000;">&quot;Woolly Window 1&quot;</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">width</span> <span style="color: #cc66cc;">640</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">height</span> <span style="color: #cc66cc;">480</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#40;</span>but <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>button<span style="color: #66cc66;">=</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">offset-x</span> <span style="color: #cc66cc;">40</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">offset-y</span> <span style="color: #cc66cc;">40</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">width</span> <span style="color: #cc66cc;">300</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">height</span> <span style="color: #cc66cc;">100</span>
                               <span style="color: #66cc66;">:</span><span style="color: #555;">font</span> font
                               <span style="color: #66cc66;">:</span><span style="color: #555;">label</span> <span style="color: #ff0000;">&quot;Button&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">display-window</span> win<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">add</span> win but<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">main-loop</span> app<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">destroy-window</span> win<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div>
<p>Next up on my agenda is to make the background and button prettier.  It should be easy enough to do with <b>GL_LIGHTING</b> and some vertex-coloring for gradations.  After that, it&#8217;s on to more controls like labels, panels, checkboxes, drop-downs, borders, and (my dread) text input boxes.  Then, it&#8217;s on to a layout manager.</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/11/woolly-peek1.png"><img src="http://nklein.com/wp-content/uploads/2009/11/woolly-peek1-150x117.png" alt="woolly-peek" title="woolly-peek" width="150" height="117" class="alignright size-thumbnail wp-image-1013" /></a>Edit: Here&#8217;s the same GUI a day later.  I&#8217;m using a simple lighting scheme and rendering the button in 3D.  I haven&#8217;t yet hooked in the bit to render it depressed when the button is pressed.  I&#8217;ve tested the code that draws it the other way, but I haven&#8217;t hooked it into the mouse handlers yet.</p>
<p>Edit #2: Actually, it only took a few minutes for me to hook in the rendering it pressed vs. unpressed.  When I did it though, it looked like the label was sliding around because the effect of the contrast between the light and dark edges of the button was so great that you perceive the whole button sliding when it&#8217;s pressed.  So, I added a little bit in there to actually slide the text by an amount close to what is perceived.  So, now&#8230; it looks pretty spiffy.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

