<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/cinap_lenrek/draw.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>&rsquo;s /usr/web/sources/contrib/cinap_lenrek/draw.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include "vnc.h"
#include "vncv.h"

static struct {
       char    *name;
       int     num;
} enctab[] = {
       "copyrect",     EncCopyRect,
       "corre",        EncCorre,
       "hextile",      EncHextile,
       "raw",          EncRaw,
       "rre",          EncRre,
       "mousewarp",    EncMouseWarp,
};

static  uchar   *pixbuf;
static  uchar   *linebuf;
static  int     vpixb;
static  int     pixb;
static  void    (*pixcp)(uchar*, uchar*);

static void
vncrdcolor(Vnc *v, uchar *color)
{
       vncrdbytes(v, color, vpixb);

       if(cvtpixels)
               (*cvtpixels)(color, color, 1);
}

void
sendencodings(Vnc *v)
{
       char *f[10];
       int enc[10], nenc, i, j, nf;

       nf = tokenize(encodings, f, nelem(f));
       nenc = 0;
       for(i=0; i&lt;nf; i++){
               for(j=0; j&lt;nelem(enctab); j++)
                       if(strcmp(f[i], enctab[j].name) == 0)
                               break;
               if(j == nelem(enctab)){
                       print("warning: unknown encoding %s\n", f[i]);
                       continue;
               }
               enc[nenc++] = enctab[j].num;
       }

       vnclock(v);
       vncwrchar(v, MSetEnc);
       vncwrchar(v, 0);
       vncwrshort(v, nenc);
       for(i=0; i&lt;nenc; i++)
               vncwrlong(v, enc[i]);
       vncflush(v);
       vncunlock(v);
}

void
requestupdate(Vnc *v, int incremental)
{
       int x, y;

       lockdisplay(display);
       x = Dx(screen-&gt;r);
       y = Dy(screen-&gt;r);
       unlockdisplay(display);
       if(x &gt; v-&gt;dim.x)
               x = v-&gt;dim.x;
       if(y &gt; v-&gt;dim.y)
               y = v-&gt;dim.y;
       vnclock(v);
       vncwrchar(v, MFrameReq);
       vncwrchar(v, incremental);
       vncwrrect(v, Rpt(ZP, Pt(x, y)));
       vncflush(v);
       vncunlock(v);
}

static Rectangle
clippixbuf(Rectangle r, int maxx, int maxy)
{
       int y, h, stride1, stride2;

       if(r.min.x &gt; maxx || r.min.y &gt; maxy){
               r.max.x = 0;
               return r;
       }
       if(r.max.y &gt; maxy)
               r.max.y = maxy;
       if(r.max.x &lt;= maxx)
               return r;

       stride2 = Dx(r) * pixb;
       r.max.x = maxx;
       stride1 = Dx(r) * pixb;
       h = Dy(r);
       for(y = 0; y &lt; h; y++)
               memmove(&amp;pixbuf[y * stride1], &amp;pixbuf[y * stride2], stride1);

       return r;
}

/* must be called with display locked */
static void
updatescreen(Rectangle r)
{
       int b, bb;
       Image *i;

       lockdisplay(display);
       if(r.max.x &gt; Dx(screen-&gt;r) || r.max.y &gt; Dy(screen-&gt;r)){
               r = clippixbuf(r, Dx(screen-&gt;r), Dy(screen-&gt;r));
               if(r.max.x == 0){
                       unlockdisplay(display);
                       return;
               }
       }

       b = Dx(r) * pixb * Dy(r);

       if(i = allocimage(display, r, screen-&gt;chan, 0, DNofill)){
               loadimage(i, r, pixbuf, b);
               draw(screen, rectaddpt(r, screen-&gt;r.min), i, nil, r.min);
               freeimage(i);
       }

       /*
        * assume load image fails only because of resize
       bb = loadimage(screen, rectaddpt(r, screen-&gt;r.min), pixbuf, b);
       if(bb != b &amp;&amp; verbose)
               fprint(2, "loadimage %d on %R for %R returned %d: %r\n", b, rectaddpt(r, screen-&gt;r.min), screen-&gt;r, bb);
        */

       unlockdisplay(display);
}

static void
fillrect(Rectangle r, int stride, uchar *color)
{
       int x, xe, y, off;

       y = r.min.y;
       off = y * stride;
       for(; y &lt; r.max.y; y++){
               xe = off + r.max.x * pixb;
               for(x = off + r.min.x * pixb; x &lt; xe; x += pixb)
                       (*pixcp)(&amp;pixbuf[x], color);
               off += stride;
       }
}

static void
loadbuf(Vnc *v, Rectangle r, int stride)
{
       int off, y;

       if(cvtpixels){
               y = r.min.y;
               off = y * stride;
               for(; y &lt; r.max.y; y++){
                       vncrdbytes(v, linebuf, Dx(r) * vpixb);
                       (*cvtpixels)(&amp;pixbuf[off + r.min.x * pixb], linebuf, Dx(r));
                       off += stride;
               }
       }else{
               y = r.min.y;
               off = y * stride;
               for(; y &lt; r.max.y; y++){
                       vncrdbytes(v, &amp;pixbuf[off + r.min.x * pixb], Dx(r) * pixb);
                       off += stride;
               }
       }
}

static Rectangle
hexrect(ushort u)
{
       int x, y, w, h;

       x = u&gt;&gt;12;
       y = (u&gt;&gt;8)&amp;15;
       w = ((u&gt;&gt;4)&amp;15)+1;
       h = (u&amp;15)+1;

       return Rect(x, y, x+w, y+h);
}


static void
dohextile(Vnc *v, Rectangle r, int stride)
{
       ulong bg, fg, c;
       int enc, nsub, sx, sy, w, h, th, tw;
       Rectangle sr, ssr;

       fg = bg = 0;
       h = Dy(r);
       w = Dx(r);
       for(sy = 0; sy &lt; h; sy += HextileDim){
               th = h - sy;
               if(th &gt; HextileDim)
                       th = HextileDim;
               for(sx = 0; sx &lt; w; sx += HextileDim){
                       tw = w - sx;
                       if(tw &gt; HextileDim)
                               tw = HextileDim;

                       sr = Rect(sx, sy, sx + tw, sy + th);
                       enc = vncrdchar(v);
                       if(enc &amp; HextileRaw){
                               loadbuf(v, sr, stride);
                               continue;
                       }

                       if(enc &amp; HextileBack)
                               vncrdcolor(v, (uchar*)&amp;bg);
                       fillrect(sr, stride, (uchar*)&amp;bg);

                       if(enc &amp; HextileFore)
                               vncrdcolor(v, (uchar*)&amp;fg);

                       if(enc &amp; HextileRects){
                               nsub = vncrdchar(v);
                               (*pixcp)((uchar*)&amp;c, (uchar*)&amp;fg);
                               while(nsub-- &gt; 0){
                                       if(enc &amp; HextileCols)
                                               vncrdcolor(v, (uchar*)&amp;c);
                                       ssr = rectaddpt(hexrect(vncrdshort(v)), sr.min);
                                       fillrect(ssr, stride, (uchar*)&amp;c);
                               }
                       }
               }
       }
}

static void
dorectangle(Vnc *v)
{
       ulong type;
       long n, stride;
       ulong color;
       Point p;
       Rectangle r, subr, maxr;

       r = vncrdrect(v);
       if(r.min.x == r.max.x || r.min.y == r.max.y)
               return;
       if(!rectinrect(r, Rpt(ZP, v-&gt;dim)))
               sysfatal("bad rectangle from server: %R not in %R", r, Rpt(ZP, v-&gt;dim));
       stride = Dx(r) * pixb;
       type = vncrdlong(v);
       switch(type){
       default:
               sysfatal("bad rectangle encoding from server");
               break;
       case EncRaw:
               loadbuf(v, Rpt(ZP, Pt(Dx(r), Dy(r))), stride);
               updatescreen(r);
               break;

       case EncCopyRect:
               p = vncrdpoint(v);
               lockdisplay(display);
               p = addpt(p, screen-&gt;r.min);
               r = rectaddpt(r, screen-&gt;r.min);
               draw(screen, r, screen, nil, p);
               unlockdisplay(display);
               break;

       case EncRre:
       case EncCorre:
               maxr = Rpt(ZP, Pt(Dx(r), Dy(r)));
               n = vncrdlong(v);
               vncrdcolor(v, (uchar*)&amp;color);
               fillrect(maxr, stride, (uchar*)&amp;color);
               while(n-- &gt; 0){
                       vncrdcolor(v, (uchar*)&amp;color);
                       if(type == EncRre)
                               subr = vncrdrect(v);
                       else
                               subr = vncrdcorect(v);
                       if(!rectinrect(subr, maxr))
                               sysfatal("bad encoding from server");
                       fillrect(subr, stride, (uchar*)&amp;color);
               }
               updatescreen(r);
               break;

       case EncHextile:
               dohextile(v, r, stride);
               updatescreen(r);
               break;

       case EncMouseWarp:
               mousewarp(r.min);
               break;
       }
}

static void
pixcp8(uchar *dst, uchar *src)
{
       *dst = *src;
}

static void
pixcp16(uchar *dst, uchar *src)
{
       *(ushort*)dst = *(ushort*)src;
}

static void
pixcp32(uchar *dst, uchar *src)
{
       *(ulong*)dst = *(ulong*)src;
}

static void
pixcp24(uchar *dst, uchar *src)
{
       dst[0] = src[0];
       dst[1] = src[1];
       dst[2] = src[2];
}

static int
calcpixb(int bpp)
{
       if(bpp / 8 * 8 != bpp)
               sysfatal("can't handle your screen");
       return bpp / 8;
}

void
readfromserver(Vnc *v)
{
       uchar type;
       uchar junk[100];
       long n;

       vpixb = calcpixb(v-&gt;bpp);
       pixb = calcpixb(screen-&gt;depth);
       switch(pixb){
       case 1:
               pixcp = pixcp8;
               break;
       case 2:
               pixcp = pixcp16;
               break;
       case 3:
               pixcp = pixcp24;
               break;
       case 4:
               pixcp = pixcp32;
               break;
       default:
               sysfatal("can't handle your screen: bad depth %d", pixb);
       }
       linebuf = malloc(v-&gt;dim.x * vpixb);
       pixbuf = malloc(v-&gt;dim.x * pixb * v-&gt;dim.y);
       if(linebuf == nil || pixbuf == nil)
               sysfatal("can't allocate pix decompression storage");
       for(;;){
               type = vncrdchar(v);
               switch(type){
               default:
                       sysfatal("bad message from server");
                       break;
               case MFrameUpdate:
                       vncrdchar(v);
                       n = vncrdshort(v);
                       while(n-- &gt; 0)
                               dorectangle(v);
                       flushimage(display, 1);
                       requestupdate(v, 1);
                       break;

               case MSetCmap:
                       vncrdbytes(v, junk, 3);
                       n = vncrdshort(v);
                       vncgobble(v, n*3*2);
                       break;

               case MBell:
                       break;

               case MSAck:
                       break;

               case MSCut:
                       vncrdbytes(v, junk, 3);
                       n = vncrdlong(v);
                       writesnarf(v, n);
                       break;
               }
       }
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:[email protected]">[email protected]</a>.</span>
</font></center>
</body>
</html>