Example #1
0
/**
 * @brief Prints text on the screen.
 *
 * @usage gfx.print( nil, "Hello World!", 50, 50, colour.new("Red") ) -- Displays text in red at 50,50.
 * @usage gfx.print( true, "Hello World!", 50, 50, col, 100 ) -- Displays text to a maximum of 100 pixels wide.
 * @usage gfx.print( true, str, 50, 50, col, 100, true ) -- Displays centered text to a maximum of 100 pixels.
 *
 *    @luaparam small Whether or not to use a small font.
 *    @luaparam str String to print.
 *    @luaparam x X position to print at.
 *    @luaparam y Y position to print at.
 *    @luaparam col Colour to print text.
 *    @luaparam max Optional parameter to indicate maximum width to render up to.
 *    @luaparam center Optional boolean parameter indicating whether or not to center it.
 * @luafunc print( small, str, x, y, col, max, center )
 */
static int gfxL_print( lua_State *L )
{
   glFont *font;
   const char *str;
   double x, y;
   LuaColour *lc;
   int max, mid;

   /* Parse parameters. */
   font  = lua_toboolean(L,1) ? &gl_smallFont : &gl_defFont;
   str   = luaL_checkstring(L,2);
   x     = luaL_checknumber(L,3);
   y     = luaL_checknumber(L,4);
   lc    = luaL_checkcolour(L,5);
   if (lua_gettop(L) >= 6)
      max = luaL_checkinteger(L,6);
   else
      max = 0;
   mid   = lua_toboolean(L,7);

   /* Render. */
   if (mid)
      gl_printMidRaw( font, max, x, y, &lc->col, str );
   else if (max > 0)
      gl_printMaxRaw( font, max, x, y, &lc->col, str );
   else
      gl_printRaw( font, x, y, &lc->col, str );
   return 0;
}
Example #2
0
/**
 * @brief Renders a button widget.
 *
 *    @param btn WIDGET_BUTTON widget to render.
 *    @param bx Base X position.
 *    @param by Base Y position.
 */
static void btn_render( Widget* btn, double bx, double by )
{
   glColour *c, *dc, *lc;
   double x, y;

   x = bx + btn->x;
   y = by + btn->y;

   /* set the colours */
   if (btn->dat.btn.disabled==1) {
      lc = &cGrey60;
      c = &cGrey20;
      dc = &cGrey40;
   }
   else {
      switch (btn->status) {
         case WIDGET_STATUS_NORMAL:
            lc = &cGrey80;
            c = &cGrey60;
            dc = &cGrey40;
            break;
         case WIDGET_STATUS_MOUSEOVER:
            lc = &cGrey90;
            c = &cGrey70;
            dc = &cGrey50;
            break;
         case WIDGET_STATUS_MOUSEDOWN:
            lc = &cGrey90;
            c = &cGrey50;
            dc = &cGrey70;
            break;
         default:
            break;
      }
   }


   /* shaded base */
   if (btn->dat.btn.disabled==1) {
      toolkit_drawRect( x, y,            btn->w, 0.4*btn->h, dc, NULL );
      toolkit_drawRect( x, y+0.4*btn->h, btn->w, 0.6*btn->h, dc, c );
   }
   else {
      toolkit_drawRect( x, y,            btn->w, 0.6*btn->h, dc, c );
      toolkit_drawRect( x, y+0.6*btn->h, btn->w, 0.4*btn->h, c, NULL );
   }
   
   /* inner outline */
   toolkit_drawOutline( x, y, btn->w, btn->h, 0., lc, c );
   /* outter outline */
   toolkit_drawOutline( x, y, btn->w, btn->h, 1., &cBlack, NULL );

   gl_printMidRaw( NULL, (int)btn->w,
         bx + (double)SCREEN_W/2. + btn->x,
         by + (double)SCREEN_H/2. + btn->y + (btn->h - gl_defFont.h)/2.,
         &cDarkRed, btn->dat.btn.display );
}
Example #3
0
File: news.c Project: Arakash/naev
/**
 * @brief Renders a news widget.
 *
 *    @param bx Base X position to render at.
 *    @param by Base Y positoin to render at.
 *    @param w Width of the widget.
 *    @param h Height of the widget.
 */
static void news_render( double bx, double by, double w, double h, void *data )
{
   (void) data;
   int i;
   unsigned int t;
   double y, dt;

   t = SDL_GetTicks();

   /* Calculate offset. */
   if (!news_drag) {
      dt = (double)(t-news_tick)/1000.;
      news_pos += dt * 25.;
   }
   news_tick = t;

   /* Make sure user isn't silly and drags it to negative values. */
   if (news_pos < 0.)
      news_pos += (news_font->h + 5.) * news_nlines + h + 3;

   /* background */
   gl_renderRect( bx, by, w, h, &cBlack );

   /* Render the text. */
   i = (int)(news_pos / (news_font->h + 5.));
   if (i > news_nlines + (int)(h/(news_font->h + 5.)) + 3) {
      news_pos = 0.;
      return;
   }

   /* Get start position. */
   y = news_pos - (i+1) * (news_font->h + 5.) - 10.;

   /* Draw loop. */
   while (i >= 0) {

      /* Skip in line isn't valid. */
      if (i >= news_nlines) {
         i--;
         y += news_font->h + 5.;
         continue;
      }

      gl_printMidRaw( news_font, w-40.,
            bx+10 + (double)SCREEN_W/2., by+y + (double)SCREEN_H/2.,
            &cConsole, news_lines[i] );

      /* Increment line and position. */
      i--;
      y += news_font->h + 5.;
   }

}
Example #4
0
/**
 * @brief Renders the overlays.
 */
void omsg_render( double dt )
{
   int i, j;
   double x, y;
   omsg_t *omsg;
   glFont *font;
   glColour col;

   /* Case nothing to do. */
   if (omsg_array == NULL)
      return;

   /* Center. */
   x  = omsg_center_x - omsg_center_w/2.;
   y  = omsg_center_y;

   /* Render. */
   for (i=0; i<array_size(omsg_array); i++) {
      omsg  = &omsg_array[i];

      /* Check if time to erase. */
      omsg->duration -= dt;
      if (omsg->duration < 0.) {
         omsg_free( omsg );
         array_erase( &omsg_array, &omsg[0], &omsg[1] );
         i--;
         continue;
      }

      /* Must have a message. */
      if (omsg->msg == NULL)
         continue;

      /* Render. */
      font = omsg_getFont( omsg->font );
      memcpy( &col, omsg->col, sizeof(glColour) );
      if (omsg->duration < 1.)
         col.a = omsg->duration;
      for (j=0; j<omsg->nlines; j++) {
         y -= font->h * 1.5;
         if (j>0)
            gl_printRestoreLast();
         gl_printMidRaw( font, omsg_center_w, x, y, &col, omsg->msg[j] );
      }
   }
}
Example #5
0
File: text.c Project: zid/naev
/**
 * @brief Renders a text widget.
 *
 *    @param txt Text widget to render.
 *    @param bx Base X position.
 *    @param by Base Y position.
 */
static void txt_render( Widget* txt, double bx, double by )
{
   /* Must have text to display. */
   if (txt->dat.txt.text==NULL)
      return;
   
   if (txt->dat.txt.centered)
      gl_printMidRaw( txt->dat.txt.font, txt->w,
            bx + (double)SCREEN_W/2. + txt->x,
            by + (double)SCREEN_H/2. + txt->y,
            txt->dat.txt.colour, txt->dat.txt.text );
   else
      gl_printTextRaw( txt->dat.txt.font, txt->w, txt->h,
            bx + (double)SCREEN_W/2. + txt->x,
            by + (double)SCREEN_H/2. + txt->y,
            txt->dat.txt.colour, txt->dat.txt.text );
}
Example #6
0
File: font.c Project: nenau/naev
/**
 * @brief Displays text centered in position and width.
 *
 * Will truncate if text is too long.
 *
 *    @param ft_font Font to use (NULL defaults to gl_defFont)
 *    @param width Width of area to center in.
 *    @param x X position to display text at.
 *    @param y Y position to display text at.
 *    @param c Colour to use for text (NULL defaults to white).
 *    @param fmt Text to display formatted like printf.
 *    @return The number of characters it had to truncate.
 */
int gl_printMid( const glFont *ft_font, const int width,
      double x, const double y,
      const glColour* c, const char *fmt, ... )
{
   /*float h = ft_font->h / .63;*/ /* slightly increase fontsize */
   char text[256]; /* holds the string */
   va_list ap;

   if (fmt == NULL) return -1;
   else { /* convert the symbols to text */
      va_start(ap, fmt);
      vsnprintf(text, 256, fmt, ap);
      va_end(ap);
   }

   return gl_printMidRaw( ft_font, width, x, y, c, text );
}
Example #7
0
/**
 * @brief Renders an image array.
 *
 *    @param iar Image array widget to render.
 *    @param bx Base X position.
 *    @param by Base Y position.
 */
static void iar_render( Widget* iar, double bx, double by )
{
   int i,j, pos;
   double x,y, w,h, xcurs,ycurs;
   double scroll_pos;
   int xelem, yelem;
   double xspace;
   glColour *c, *dc, *lc, tc, fontcolour;
   int is_selected;
   int tw;
   double d;

   /*
    * Calculations.
    */
   /* position */
   x = bx + iar->x;
   y = by + iar->y;

   /* element dimensions */
   iar_getDim( iar, &w, &h );

   /* number of elements */
   xelem = iar->dat.iar.xelem;
   yelem = iar->dat.iar.yelem;
   xspace = (double)(((int)iar->w - 10) % (int)w) / (double)(xelem + 1);

   /* background */
   toolkit_drawRect( x, y, iar->w, iar->h, &cBlack, NULL );

   /*
    * Scrollbar.
    */
   d          = h * (yelem - (int)(iar->h / h));
   if (fabs(d) < 1e-05)
      scroll_pos = 0.;
   else
      scroll_pos = iar->dat.iar.pos / d;
   toolkit_drawScrollbar( x + iar->w - 10., y, 10., iar->h, scroll_pos );

   /*
    * Main drawing loop.
    */
   gl_clipRect( x, y, iar->w, iar->h );
   ycurs = y + iar->h - h + iar->dat.iar.pos;
   for (j=0; j<yelem; j++) {
      xcurs = x + xspace;
      for (i=0; i<xelem; i++) {

         /* Get position. */
         pos = j*xelem + i;

         /* Out of elements. */
         if ((pos) >= iar->dat.iar.nelements)
            break;

         is_selected = (iar->dat.iar.selected == pos) ? 1 : 0;

         fontcolour = cWhite;
         /* Draw background. */
         if (is_selected)
            toolkit_drawRect( xcurs + 2.,
                  ycurs + 2.,
                  w - 5., h - 5., &cDConsole, NULL );
         else if (iar->dat.iar.background != NULL) {
            toolkit_drawRect( xcurs + 2.,
                  ycurs + 2.,
                  w - 5., h - 5., &iar->dat.iar.background[pos], NULL );

            tc = iar->dat.iar.background[pos];

            if (((tc.r + tc.g + tc.b) / 3) > 0.5)
               fontcolour = cBlack;
         }

         /* image */
         if (iar->dat.iar.images[pos] != NULL)
            gl_blitScale( iar->dat.iar.images[pos],
                  xcurs + 5., ycurs + gl_smallFont.h + 7.,
                  iar->dat.iar.iw, iar->dat.iar.ih, NULL );

         /* caption */
         if (iar->dat.iar.captions[pos] != NULL)
            gl_printMidRaw( &gl_smallFont, iar->dat.iar.iw, xcurs + 5., ycurs + 5.,
                     (is_selected) ? &cBlack : &fontcolour,
                     iar->dat.iar.captions[pos] );

         /* quantity. */
         if (iar->dat.iar.quantity != NULL) {
            if (iar->dat.iar.quantity[pos] != NULL) {
               /* Rectangle to highlight better. */
               tw = gl_printWidthRaw( &gl_smallFont,
                     iar->dat.iar.quantity[pos] );

               if (is_selected)
                  tc = cDConsole;
               else if (iar->dat.iar.background != NULL)
                  tc = iar->dat.iar.background[pos];
               else
                  tc = cBlack;

               tc.a = 0.75;
               toolkit_drawRect( xcurs + 2.,
                     ycurs + 5. + iar->dat.iar.ih,
                     tw + 4., gl_smallFont.h + 4., &tc, NULL );
               /* Quantity number. */
               gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw,
                     xcurs + 5., ycurs + iar->dat.iar.ih + 7.,
                     &fontcolour, iar->dat.iar.quantity[pos] );
            }
         }

         /* Slot type. */
         if (iar->dat.iar.slottype != NULL) {
            if (iar->dat.iar.slottype[pos] != NULL) {
               /* Rectangle to highlight better. Width is a hack due to lack of monospace font. */
               tw = gl_printWidthRaw( &gl_smallFont, "M" );

               if (is_selected)
                  tc = cDConsole;
               else if (iar->dat.iar.background != NULL)
                  tc = iar->dat.iar.background[pos];
               else
                  tc = cBlack;

               tc.a = 0.75;
               toolkit_drawRect( xcurs + iar->dat.iar.iw - 6.,
                     ycurs + 5. + iar->dat.iar.ih,
                     tw + 2., gl_smallFont.h + 4., &tc, NULL );
               /* Slot size letter. */
               gl_printMaxRaw( &gl_smallFont, iar->dat.iar.iw,
                     xcurs + iar->dat.iar.iw - 4., ycurs + iar->dat.iar.ih + 7.,
                     &fontcolour, iar->dat.iar.slottype[pos] );
            }
         }

         /* outline */
         if (is_selected) {
            lc = &cWhite;
            c = &cGrey80;
            dc = &cGrey60;
         }
         else {
            lc = toolkit_colLight;
            c = toolkit_col;
            dc = toolkit_colDark;
         }
         toolkit_drawOutline( xcurs + 2.,
               ycurs + 2.,
               w - 4., h - 4., 1., lc, c );
         toolkit_drawOutline( xcurs + 2.,
               ycurs + 2.,
               w - 4., h - 4., 2., dc, NULL );
         xcurs += w + xspace;
      }
      ycurs -= h;
   }
   gl_unclipRect();

   /*
    * Final outline.
    */
   toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 1., toolkit_colLight, toolkit_col );
   toolkit_drawOutline( x+1, y+1, iar->w-2, iar->h-2, 2., toolkit_colDark, NULL );
}
Example #8
0
File: toolkit.c Project: Delll/naev
/**
 * @brief Renders a window border.
 *
 *    @param w Window to render
 */
static void window_renderBorder( Window* w )
{
   int i;
   GLint cx, cy;
   double x, y;
   glColour *lc, *c, *dc, *oc;
   GLint vertex[31*4];
   GLfloat colours[31*4];

   /* position */
   x = w->x - (double)SCREEN_W/2.;
   y = w->y - (double)SCREEN_H/2.;

   /* colours */
   lc = &cGrey90;
   c = &cGrey70;
   dc = &cGrey50;
   oc = &cGrey30;

   /*
    * Case fullscreen.
    */
   if (window_isFlag( w, WINDOW_FULLSCREEN )) {
      /* Background. */
      toolkit_drawRect( x, y,          w->w, 0.6*w->h, dc, c );
      toolkit_drawRect( x, y+0.6*w->h, w->w, 0.4*w->h, c, NULL );
      /* Name. */
      gl_printMidRaw( &gl_defFont, w->w,
            x + (double)SCREEN_W/2.,
            y + w->h - 20. + (double)SCREEN_H/2.,
            &cBlack, w->name );
      return;
   }

   /*
    * window shaded bg
    */
   /* main body */
   toolkit_drawRect( x+21, y,          w->w-42., 0.6*w->h, dc, c );
   toolkit_drawRect( x+21, y+0.6*w->h, w->w-42., 0.4*w->h, c, NULL );

   glShadeModel(GL_SMOOTH);
   /* Both sides. */
   gl_vboActivateOffset( toolkit_vbo, GL_COLOR_ARRAY,
         toolkit_vboColourOffset, 4, GL_FLOAT, 0 );
   gl_vboActivateOffset( toolkit_vbo, GL_VERTEX_ARRAY, 0, 2, GL_INT, 0 );
   /* Colour is shared. */
   colours[0] = c->r;
   colours[1] = c->g;
   colours[2] = c->r;
   colours[3] = c->a;
   for (i=0; i<7; i++) {
      colours[4 + 4*i + 0] = dc->r;
      colours[4 + 4*i + 1] = dc->g;
      colours[4 + 4*i + 2] = dc->r;
      colours[4 + 4*i + 3] = dc->a;
   }
   for (i=0; i<8; i++) {
      colours[32 + 4*i + 0] = c->r;
      colours[32 + 4*i + 1] = c->g;
      colours[32 + 4*i + 2] = c->r;
      colours[32 + 4*i + 3] = c->a;
   }
   gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset,
         sizeof(GLfloat) * 4*16, colours );
   /* Left side vertex. */
   cx = x;
   cy = y;
   vertex[0]  = cx + 21;
   vertex[1]  = cy + 0.6*w->h;
   vertex[2]  = cx + 21;
   vertex[3]  = cy;
   vertex[4]  = cx + 15;
   vertex[5]  = cy + 1;
   vertex[6]  = cx + 10;
   vertex[7]  = cy + 3;
   vertex[8]  = cx + 6;
   vertex[9]  = cy + 6;
   vertex[10] = cx + 3;
   vertex[11] = cy + 10;
   vertex[12] = cx + 1;
   vertex[13] = cy + 15;
   vertex[14] = cx;
   vertex[15] = cy + 21;
   vertex[16] = cx;
   vertex[17] = cy + 0.6*w->h;
   vertex[18] = cx;
   cy = y + w->h;
   vertex[19] = cy - 21;
   vertex[20] = cx + 1;
   vertex[21] = cy - 15;
   vertex[22] = cx + 3;
   vertex[23] = cy - 10;
   vertex[24] = cx + 6;
   vertex[25] = cy - 6;
   vertex[26] = cx + 10;
   vertex[27] = cy - 3;
   vertex[28] = cx + 15;
   vertex[29] = cy - 1;
   vertex[30] = cx + 21;
   vertex[31] = cy;
   gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*16, vertex );
   glDrawArrays( GL_POLYGON, 0, 16 );
   /* Right side vertex. */
   cx = x + w->w;
   cy = y;
   vertex[0]  = cx - 21;
   vertex[1]  = cy + 0.6*w->h;
   vertex[2]  = cx - 21;
   vertex[3]  = cy;
   vertex[4]  = cx - 15;
   vertex[5]  = cy + 1;
   vertex[6]  = cx - 10;
   vertex[7]  = cy + 3;
   vertex[8]  = cx - 6;
   vertex[9]  = cy + 6;
   vertex[10] = cx - 3;
   vertex[11] = cy + 10;
   vertex[12] = cx - 1;
   vertex[13] = cy + 15;
   vertex[14] = cx;
   vertex[15] = cy + 21;
   vertex[16] = cx;
   vertex[17] = cy + 0.6*w->h;
   vertex[18] = cx;
   cy = y + w->h;
   vertex[19] = cy - 21;
   vertex[20] = cx - 1;
   vertex[21] = cy - 15;
   vertex[22] = cx - 3;
   vertex[23] = cy - 10;
   vertex[24] = cx - 6;
   vertex[25] = cy - 6;
   vertex[26] = cx - 10;
   vertex[27] = cy - 3;
   vertex[28] = cx - 15;
   vertex[29] = cy - 1;
   vertex[30] = cx - 21;
   vertex[31] = cy;
   gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*16, vertex );
   glDrawArrays( GL_POLYGON, 0, 16 );


   /* 
    * inner outline
    */
   /* Colour. */
   for (i=0; i<7; i++) {
      colours[4*i + 0] = c->r;
      colours[4*i + 1] = c->g;
      colours[4*i + 2] = c->b;
      colours[4*i + 3] = c->a;
   }
   for (; i<7+16; i++) {
      colours[4*i + 0] = lc->r;
      colours[4*i + 1] = lc->g;
      colours[4*i + 2] = lc->b;
      colours[4*i + 3] = lc->a;
   }
   for (; i<7+16+8; i++) {
      colours[4*i + 0] = c->r;
      colours[4*i + 1] = c->g;
      colours[4*i + 2] = c->b;
      colours[4*i + 3] = c->a;
   }
   gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset,
         sizeof(GLfloat) * 4*31, colours );
   /* Vertex. */
   /* Left side. */
   cx = x + 1;
   cy = y + 1;
   vertex[0]  = cx + 21;
   vertex[1]  = cy;
   vertex[2]  = cx + 15;
   vertex[3]  = cy + 1;
   vertex[4]  = cx + 10;
   vertex[5]  = cy + 3;
   vertex[6]  = cx + 6;
   vertex[7]  = cy + 6;
   vertex[8]  = cx + 3;
   vertex[9]  = cy + 10;
   vertex[10] = cx + 1;
   vertex[11] = cy + 15;
   vertex[12] = cx;
   vertex[13] = cy + 21;
   vertex[14] = cx;
   vertex[15] = cy + 0.6*w->h - 1;
   cy = y + w->h - 1;
   vertex[16] = cx;
   vertex[17] = cy - 21;
   vertex[18] = cx + 1;
   vertex[19] = cy - 15;
   vertex[20] = cx + 3;
   vertex[21] = cy - 10;
   vertex[22] = cx + 6;
   vertex[23] = cy - 6;
   vertex[24] = cx + 10;
   vertex[25] = cy - 3;
   vertex[26] = cx + 15;
   vertex[27] = cy - 1;
   vertex[28] = cx + 21;
   vertex[29] = cy;
   /* Right side via top. */
   cx = x + w->w - 1;
   cy = y + w->h - 1;
   vertex[30] = cx - 21;
   vertex[31] = cy;
   vertex[32] = cx - 15;
   vertex[33] = cy - 1;
   vertex[34] = cx - 10;
   vertex[35] = cy - 3;
   vertex[36] = cx - 6;
   vertex[37] = cy - 6;
   vertex[38] = cx - 3;
   vertex[39] = cy - 10;
   vertex[40] = cx - 1;
   vertex[41] = cy - 15;
   vertex[42] = cx;
   vertex[43] = cy - 21;
   cy = y + 1;
   vertex[44] = cx;
   vertex[45] = cy + 0.6*w->h - 1;
   vertex[46] = cx;
   vertex[47] = cy + 21;
   vertex[48] = cx - 1;
   vertex[49] = cy + 15;
   vertex[50] = cx - 3;
   vertex[51] = cy + 10;
   vertex[52] = cx - 6;
   vertex[53] = cy + 6;
   vertex[54] = cx - 10;
   vertex[55] = cy + 3;
   vertex[56] = cx - 15;
   vertex[57] = cy + 1;
   vertex[58] = cx - 21;
   vertex[59] = cy;
   cx = x + 1;
   cy = y + 1;
   vertex[60] = cx + 21;
   vertex[61] = cy;
   gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*31, vertex );
   glDrawArrays( GL_LINE_LOOP, 0, 31 );


   /*
    * outter outline
    */
   glShadeModel(GL_FLAT);
   /* Colour. */
   for (i=0; i<31; i++) {
      colours[4*i + 0] = oc->r;
      colours[4*i + 1] = oc->g;
      colours[4*i + 2] = oc->b;
      colours[4*i + 3] = oc->a;
   }
   gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset,
         sizeof(GLfloat) * 4*31, colours );
   /* Vertex. */
   /* Left side. */
   cx = x;
   cy = y;
   vertex[0]  = cx + 21;
   vertex[1]  = cy;
   vertex[2]  = cx + 15;
   vertex[3]  = cy + 1;
   vertex[4]  = cx + 10;
   vertex[5]  = cy + 3;
   vertex[6]  = cx + 6;
   vertex[7]  = cy + 6;
   vertex[8]  = cx + 3;
   vertex[9]  = cy + 10;
   vertex[10] = cx + 1;
   vertex[11] = cy + 15;
   vertex[12] = cx;
   vertex[13] = cy + 21;
   vertex[14] = cx;
   vertex[15] = cy + 0.6*w->h;
   cy = y + w->h;
   vertex[16] = cx;
   vertex[17] = cy - 21;
   vertex[18] = cx + 1;
   vertex[19] = cy - 15;
   vertex[20] = cx + 3;
   vertex[21] = cy - 10;
   vertex[22] = cx + 6;
   vertex[23] = cy - 6;
   vertex[24] = cx + 10;
   vertex[25] = cy - 3;
   vertex[26] = cx + 15;
   vertex[27] = cy - 1;
   vertex[28] = cx + 21;
   vertex[29] = cy;
   /* Right side via top. */
   cx = x + w->w;
   cy = y + w->h;
   vertex[30] = cx - 21;
   vertex[31] = cy;
   vertex[32] = cx - 15;
   vertex[33] = cy - 1;
   vertex[34] = cx - 10;
   vertex[35] = cy - 3;
   vertex[36] = cx - 6;
   vertex[37] = cy - 6;
   vertex[38] = cx - 3;
   vertex[39] = cy - 10;
   vertex[40] = cx - 1;
   vertex[41] = cy - 15;
   vertex[42] = cx;
   vertex[43] = cy - 21;
   cy = y;
   vertex[44] = cx;
   vertex[45] = cy + 0.6*w->h;
   vertex[46] = cx;
   vertex[47] = cy + 21;
   vertex[48] = cx - 1;
   vertex[49] = cy + 15;
   vertex[50] = cx - 3;
   vertex[51] = cy + 10;
   vertex[52] = cx - 6;
   vertex[53] = cy + 6;
   vertex[54] = cx - 10;
   vertex[55] = cy + 3;
   vertex[56] = cx - 15;
   vertex[57] = cy + 1;
   vertex[58] = cx - 21;
   vertex[59] = cy;
   cx = x;
   cy = y;
   vertex[60] = cx + 21;
   vertex[61] = cy;
   gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*31, vertex );
   glDrawArrays( GL_LINE_LOOP, 0, 31 );

   /* Clean up. */
   gl_vboDeactivate();

   /*
    * render window name
    */
   gl_printMidRaw( &gl_defFont, w->w,
         x + (double)SCREEN_W/2.,
         y + w->h - 20. + (double)SCREEN_H/2.,
         &cBlack, w->name );
}