9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: andrey mirtchovski <andrey@lanl.gov>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] draw() question
Date: Sat, 17 Aug 2002 02:45:13 -0600	[thread overview]
Message-ID: <20020817023223.K47692-400000@fbsd.acl.lanl.gov> (raw)
In-Reply-To: <bbbee9131f29845d1c92436460ce9c53@plan9.bell-labs.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 699 bytes --]

it's not hard, i'm just (to quote george carlin) minimally exceptional.

XCopyArea, whose behaviour i tried to emulate, had it the other way
around and i was tricked by it :)

included is the end result following your help. getscr contains some
help routines which grab a screenshot and squeeze it into the current
window, decayscreen is another xscreensaver hack, which just mangles
the screen in interesting ways...

8c -FVw decayscreen.c getscr.c; 8l decayscreen.8 getscr.8

andrey

On Fri, 16 Aug 2002, rob pike, esq. wrote:

> Isn't it just
>
> draw(dst, Rect(x, y, x+(x2-x1), y+(y2-y1)), src, nil, Pt(x1, y1)) ?
>
> Why is this hard?  Or what have I missed?
>
> -rob
>

[-- Attachment #2: Type: TEXT/PLAIN, Size: 1947 bytes --]

#include <u.h>
#include <libc.h>
#include <draw.h>
#include "getscr.h"
/*
  * allocates temporary storage for and reads
  * /dev/screen... modified from of lens.c
  */
uchar *
getscr(void)
{
	char 			buf[5*12];
	ulong 		chan;
	uchar		*screenbuf;
	int 			d, screenfd;


	screenfd = open("/dev/screen", OREAD);
	if(screenfd < 0)
		sysfatal("can't open /dev/screen: %r");

	if(read(screenfd, buf, sizeof buf) != sizeof buf)
		sysfatal("can't read /dev/screen: %r");

	chan = strtochan(buf);
	d = chantodepth(chan);
	if(d < 8)
		sysfatal("can't handle screen format %11.11s", buf);

	bypp = d/8;
	screenr.min.x = atoi(buf+1*12);
	screenr.min.y = atoi(buf+2*12);
	screenr.max.x = atoi(buf+3*12);
	screenr.max.y = atoi(buf+4*12);

	screenbuf = malloc(bypp*Dx(screenr)*Dy(screenr));
	if(screenbuf == nil)
		sysfatal("screen buffer malloc failed: %r");

	if(readn(screenfd, screenbuf, bypp*Dx(screenr)*Dy(screenr)) != bypp*Dx(screenr)*Dy(screenr))
		sysfatal("can't read screen: %r");
	
	return screenbuf;
}


/*
  * squeeze the screenshot to fit in the current 
  * window
  */
Image *
squeeze(uchar *buf)
{
	int x, y, xx, yy, i;
	float dx, dy;
	Image *tmp;
	uchar *out;

	if(buf == nil)
		return nil;


	tmp = allocimage(display, screen->r, screen->chan, 0, DBlack);
	if(tmp == nil)
		sysfatal("can't allocate temp image");

	dx = (float)Dx(screenr)/Dx(tmp->r);
	dy = (float)Dy(screenr)/Dy(tmp->r);

	out = (uchar *)malloc(bypp*Dx(tmp->r)*Dy(tmp->r));
	if(out == nil)
		sysfatal("can't allocate temp memory");

	for(y=0; y<Dy(tmp->r); y++){
		for(x=0; x<Dx(tmp->r); x++){
			for(i=0; i<bypp; i++) {
				yy = (int)(dy*y);
				xx = (int)(dx*x);
				out[bypp*(y*Dx(tmp->r)+x) + i] = buf[bypp*(yy*Dx(screenr)+xx)+i];
			}
		}
	}
	
	if(loadimage(tmp, tmp->r, out, bypp*Dx(tmp->r)*Dy(tmp->r)) != bypp*Dx(tmp->r)*Dy(tmp->r)){
				sysfatal("loadimage");
	}
	return(tmp);
}

[-- Attachment #3: Type: TEXT/PLAIN, Size: 85 bytes --]

uchar*	getscr(void);
Image*	squeeze(uchar *);

Rectangle		screenr;
int 			bypp;

[-- Attachment #4: Type: TEXT/PLAIN, Size: 8537 bytes --]

/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997 
 * Jamie Zawinski <jwz@jwz.org>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or 
 * implied warranty.
 */

/* decayscreen
 *
 * Based on slidescreen program from the xscreensaver application and the
 * decay program for Sun framebuffers.  This is the comment from the decay.c
 * file:

 * decay.c
 *   find the screen bitmap for the console and make it "decay" by
 *   randomly shifting random rectangles by one pixelwidth at a time.
 *
 *   by David Wald, 1988
 *        rewritten by Natuerlich!
 *   based on a similar "utility" on the Apollo ring at Yale.

 * X version by
 *
 *  Vivek Khera <khera@cs.duke.edu>
 *  5-AUG-1993
 *
 *  Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
 
 *  R. Schultz
 *  Added "melt" & "stretch" modes 28-Mar-1999
 *
 */

/* 
  * ported to Plan 9 by andrey@lanl.gov, 08/02
  */

/* plan9-related stuff */
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

/* screenshot-related stuff */
#include "getscr.h"	
static uchar *scrbuf;
static Image *scrimg;

/* other defines */
#define NULL nil
#define XPoint Point
#define NRAND nrand
#define LRAND lrand
#define random rand
#define MAXRAND ((2<<31)-1)
#define MAX(a, b) (((a) > (b))?(a):(b))
#define MIN(a, b) (((a) < (b))?(a):(b))
#define RAND_MAX MAXRAND
#define ABS abs
Image *colors[256];
#define M_PI	PI
#define Bool int
#define True 1
#define False 0

char *buttons[] = 
{
	"exit",
	0
};

Menu menu = 
{
	buttons
};
Mouse m;



/* end of plan9-related defines */

static int sizex, sizey;
static int delay = 1000;
static int mode;
static int iterations=1;

#define SHUFFLE 0
#define UP 1
#define LEFT 2
#define RIGHT 3
#define DOWN 4
#define UPLEFT 5
#define DOWNLEFT 6
#define UPRIGHT 7
#define DOWNRIGHT 8
#define IN 9
#define OUT 10
#define MELT 11
#define STRETCH 12
#define FUZZ 13

static void
init_decay (void)
{


    mode = random() % (FUZZ+1);

  delay = 10;




  sizex = Dx(screen->r);
  sizey = Dy(screen->r);

  
  if (mode == MELT || mode == STRETCH) {
    /* make sure screen eventually turns background color */
    line(screen, addpt(screen->r.min, Pt(0, 0)), 
			addpt(screen->r.min, Pt(sizex, 1)), 
			Endsquare, Endsquare, 0, display->black, ZP); 

    /* slow down for smoother melting*/
    iterations = 1;
  }

}


/*
 * perform one iteration of decay
 */
static void
decay1 (void)
{
    int left, top, width, height, toleft, totop;
	Rectangle r; Point p, p2;

#define L 101
#define R 102
#define U 103
#define D 104
    static int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
    static int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
    static int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
    static int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
    static int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };

    static int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
    static int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
    static int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
    static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
    static int *bias;

    switch (mode) {
      case SHUFFLE:	bias = no_bias; break;
      case UP:		bias = up_bias; break;
      case LEFT:	bias = left_bias; break;
      case RIGHT:	bias = right_bias; break;
      case DOWN:	bias = down_bias; break;
      case UPLEFT:	bias = upleft_bias; break;
      case DOWNLEFT:	bias = downleft_bias; break;
      case UPRIGHT:	bias = upright_bias; break;
      case DOWNRIGHT:	bias = downright_bias; break;
      case IN:		bias = no_bias; break;
      case OUT:		bias = no_bias; break;
      case MELT:	bias = no_bias; break;
      case STRETCH:	bias = no_bias; break;
      case FUZZ:	bias = no_bias; break;
     default: abort();
    }

#define nrnd(x) (random() % (x))

    if (mode == MELT || mode == STRETCH) {
      left = nrnd(sizex/2);
      top = nrnd(sizey);
      width = nrnd( sizex/2 ) + sizex/2 - left;
      height = nrnd(sizey - top);
      toleft = left;
      totop = top+1;

    } else if (mode == FUZZ) {  /* By Vince Levey <vincel@vincel.org>;
                                   inspired by the "melt" mode of the
                                   "scrhack" IrisGL program by Paul Haeberli
                                   circa 1991. */
      static int toggle = 0;

      left = nrnd(sizex - 1);
      top  = nrnd(sizey - 1);
      toggle = !toggle;
      if (toggle)
        {
          totop = top;
          height = 1;
          toleft = nrnd(sizex - 1);
          if (toleft > left)
            {
              width = toleft-left;
              toleft = left;
              left++;
            }
          else
            {
              width = left-toleft;
              left = toleft;
              toleft++;
            }
        }
      else
        {
          toleft = left;
          width = 1;
          totop  = nrnd(sizey - 1);
          if (totop > top)
            {
              height = totop-top;
              totop = top;
              top++;
            }
          else
            {
              height = top-totop;
              top = totop;
              totop++;
            }
        }

    } else {

      left = nrnd(sizex - 1);
      top = nrnd(sizey);
      width = nrnd(sizex - left);
      height = nrnd(sizey - top);
      
      toleft = left;
      totop = top;
      if (mode == IN || mode == OUT) {
	int x = left+(width/2);
	int y = top+(height/2);
	int cx = sizex/2;
	int cy = sizey/2;
	if (mode == IN) {
	  if      (x > cx && y > cy)   bias = upleft_bias;
	  else if (x < cx && y > cy)   bias = upright_bias;
	  else if (x < cx && y < cy)   bias = downright_bias;
	  else /* (x > cx && y < cy)*/ bias = downleft_bias;
	} else {
	  if      (x > cx && y > cy)   bias = downright_bias;
	  else if (x < cx && y > cy)   bias = downleft_bias;
	  else if (x < cx && y < cy)   bias = upleft_bias;
	  else /* (x > cx && y < cy)*/ bias = upright_bias;
	}
      }
      
      switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
      case L: toleft = left-1; break;
      case R: toleft = left+1; break;
      case U: totop = top-1; break;
      case D: totop = top+1; break;
      default: abort(); break;
      }
    }
    
	r = screen->r;
	if (mode == STRETCH) {
		p = addpt(r.min, Pt(0, sizey-top-1));
		p2 = addpt(r.min, Pt(0, sizey-top-2));
		r = Rpt(p, addpt(Pt(sizex, top+1), p));
//		XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1, 
//		0, sizey-top-1); 
   	} else {
		p = addpt(r.min, Pt(toleft, totop));
		p2 = addpt(r.min, Pt(left, top));
		r = Rpt(p, addpt(Pt(width, height), p));
//		XCopyArea (dpy, window, window, gc, left, top, width, height,
//		 toleft, totop);
	}

	draw(screen, r, screen, nil, p2);

#undef nrnd
}


void
screenhack (void)
{
	init_decay ();
	while (1) {
		int i;
		for (i = 0; i < iterations; i++)
			decay1 ();
		flushimage(display, 1);
		if(ecanmouse()) {
			m = emouse();
			if(m.buttons&4) {
				if(emenuhit(3, &m, &menu) == 0) 
					exits(0);
			}
		}
		if (delay) sleep (delay);
	}
}


void
eresized(int new)
{
	
	if(new && getwindow(display, Refnone) < 0) {
		sysfatal("can't reattach to window: %r");
	}

	if(scrimg != nil)
		freeimage(scrimg);
	
	scrimg = squeeze(scrbuf);
	if(scrimg == nil)
		sysfatal("unable to fit screenshot to window: %r");

	init_decay();
	draw(screen, screen->r, scrimg, nil, scrimg->r.min);
}



void 
main(int argc, char **argv)
{

	USED(argc, argv);
	srand(time(0));

	scrbuf = getscr();
	if(scrbuf == nil)
		sysfatal("could not obtain screenshot: %r");

	if(initdraw(nil, nil, "decayscreen") < 0)
		sysfatal("initdraw failed: %r");

	einit(Emouse);
	eresized(0);

	screenhack();
}

  reply	other threads:[~2002-08-17  8:45 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-16 12:14 rob pike, esq.
2002-08-17  8:45 ` andrey mirtchovski [this message]
  -- strict thread matches above, loose matches on Subject: below --
2002-08-16  7:59 andrey mirtchovski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020817023223.K47692-400000@fbsd.acl.lanl.gov \
    --to=andrey@lanl.gov \
    --cc=9fans@cse.psu.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).