diff --git a/part12-wgt/examples/wgt11.c b/part12-wgt/examples/wgt11.c index 60ef1e4..ddf41e8 100644 --- a/part12-wgt/examples/wgt11.c +++ b/part12-wgt/examples/wgt11.c @@ -51,6 +51,16 @@ void getch(void) { // ######## WGT EXAMPLES ######## +#define TIMERSPEED 60 +int timer; +int size; +int direction = -1; + +void timer_routine (void) +{ + timer++; +} + void wgt11() { block part1; /* part of the screen */ @@ -71,6 +81,39 @@ void wgt11() wputblock (0, 0, part1, 0); + getch (); + wcls (vgapal[0]); + + timer = 0; + size = 50; + winittimer (); + wstarttimer (timer_routine, TIMERSPEED); + + wclip (0, 0, 319, 199); + do { + if (direction > 0) + { + size += timer * 2; + timer = 0; + if (size > 50) + direction = -1; + } + else + { + size -= timer * 2; + timer = 0; + if (size < -1000) + direction = 1; + } + + wresize (size, size, 319 - size, 199 - size, part1, NORMAL); + + } while (1); + getch (); + + wstoptimer (); + wdonetimer (); + wfreeblock(part1); } diff --git a/part12-wgt/wgt.h b/part12-wgt/wgt.h index 1ab1dcc..6eb7700 100644 --- a/part12-wgt/wgt.h +++ b/part12-wgt/wgt.h @@ -34,6 +34,10 @@ extern unsigned char vgafont[224][8]; #define TEXTBG 1 #define TEXTFGBG 2 +/* Image transfer operations */ +#define NORMAL 0 +#define XRAY 1 + /* Pointer to the active drawing page */ typedef unsigned int *block; extern block abuf; @@ -102,3 +106,4 @@ void wstoptimer (void); void wflipblock (block image, short direction); block wloadblock (unsigned char *data); void wloadpalette (unsigned char *data, color *pal); +void wresize (short x, short y, short x2, short y2, block image, short mode); diff --git a/part12-wgt/wresize.c b/part12-wgt/wresize.c new file mode 100644 index 0000000..165b3fe --- /dev/null +++ b/part12-wgt/wresize.c @@ -0,0 +1,200 @@ +#include "wgt.h" + +void resize_horizontal_line (block src, block dest, unsigned int whole, + unsigned int xfrac, unsigned short step, short length) +/* Where: + src : is a pointer to the source bitmap + dest : is a pointer to the destination screen + whole: is the amount of pixels to increase the source pointer for every + destination pixel across + xfrac: is the initial fractional portion + step : is the fractional pixel amount to increase the source pointer for + every destination pixel across. 1 step = 1/256 of a pixel, so + every 256 fractional steps, the source pointer is increased by 1. + length : is the number of pixels to draw +*/ +{ + unsigned int px; + + for (int i=0; i 65535) { + xfrac %= 65536; + src++; + } + src += whole; + *dest = px; + dest++; + } +} + +void resize_horizontal_line_xray (block src, block dest, unsigned int whole, + unsigned int xfrac, unsigned short step, short length) +/* Where: + src : is a pointer to the source bitmap + dest : is a pointer to the destination screen + whole: is the amount of pixels to increase the source pointer for every + destination pixel across + xfrac: is the initial fractional portion + step : is the fractional pixel amount to increase the source pointer for + every destination pixel across. 1 step = 1/256 of a pixel, so + every 256 fractional steps, the source pointer is increased by 1. + length : is the number of pixels to draw +*/ +{ + unsigned int px; + + for (int i=0; i 65535) { + xfrac %= 65536; + src++; + } + src += whole; + if (px != 0) *dest = px; + dest++; + } +} + +void wresize (short x, short y, short x2, short y2, block image, short mode) +{ +long xdif, ydif; +long finalwidth, finalheight, endwidth, endheight; +long origwidth,origheight; +int i; +long endx; + +block to, from; +block fromt; +unsigned short whole; +unsigned short step; +unsigned short ywhole; +unsigned short ystep; + +unsigned long xstepper, ystepper; +unsigned long yfrac; +unsigned long xfrac; + + origwidth = wgetblockwidth (image); + origheight = wgetblockheight (image); + /* Get the original width and height of the block */ + + finalwidth = abs (x2 - x) + 1; + finalheight = abs (y2 - y) + 1; + /* Find the new width and height */ + + xstepper = ((long)(origwidth) << 16) / ((long)(finalwidth)); + /* Calculate the amount to add to the source bitmap for every pixel across. + This is done using a fixed point number by multiplying it by 65536 (<<16) + and using 0-65535 as a fractional amount. */ + + whole = xstepper >> 16; /* Keep the whole amount */ + step = xstepper - whole * 65536; + /* and the fractional amount (1/65536th of a pixel) */ + + ystepper = ((long)(origheight) << 16) / ((long)(finalheight)); + ywhole = ystepper >> 16; + ystep = ystepper - ywhole * 65536; + /* Do the same with the vertical height */ + + + to = &abuf[y*WGT_SYS.xres + x]; + /* Make an initial pointer to the destination */ + from = &image[2]; + /* Skip over the width/height integers */ + + endwidth = finalwidth; + endheight = finalheight; + + xdif = 0; + /* Differences between actual coordinates and */ + ydif = 0; /* the clipped coordinates. */ + yfrac = 0; /* Reset step to 0 */ + xfrac = 0; /* Reset step to 0 */ + + /* Do the clipping */ + if (x < tx) + { + xdif = tx - x; + /* Find the difference between x<--->tx */ + /* if we know that tx is the greater number */ + to += xdif; + /* Make sure dest is within left clipping */ + endwidth -= xdif; + /* Decrease the horizontal number of pixels drawn */ + + xfrac = (xdif * step) % 65536; + + from += ((int)xdif * xstepper) >> 16; + /* Now adjust the source pointer according to the whole and step values. + We multiply the number of pixels and the rate and add this to our + pointer. The fractional part is divided by 65536 because we're only + concerned with the whole pixel amounts. */ + } + + if (y < ty) + { + ydif = ty - y; + endheight = finalheight - (ydif); + to += ydif * WGT_SYS.xres; + yfrac = (ydif * ystep) % 65536; + + /* Do the same for the height */ + from += (((long)ydif * (long)ystepper)>>16) * (long)origwidth; + /* Same as above but also multiply be the width of the source since we're + going down a row instead of one pixel across. */ + } + + if (x + finalwidth - 1 > bx) + endwidth -= ((x + finalwidth - 1) - bx); + if (y + finalheight - 1 > by) + endheight -= ((y + finalheight - 1) - by); + /* Clip the right and bottom edges simply by decreasing the number of + pixels drawn. */ + + + if ((x2 > tx) && (y2 > ty) && (endwidth > 0)) + /* If it is even on the screen at all */ + { + endx = endwidth; + + if (mode == NORMAL) /* Plain and simple */ + for (i = 1; i <= endheight; i++) /* Vertical loop */ + { + fromt = from; + resize_horizontal_line (fromt, to, whole, xfrac, step, endx); + /* Resize one line using our assembly routine */ + + to += endx; + + yfrac += ystep; + if (yfrac > 65535) + { + yfrac -= 65535; + from += origwidth; + } + + from += ywhole * origwidth; + to += WGT_SYS.xres - endwidth; + } + else /* Use XRAY mode */ + for (i = 1; i <= endheight; i++) + { + fromt = from; + resize_horizontal_line_xray (fromt, to, whole, xfrac, step, endx); + to += endx; + + yfrac += ystep; + if (yfrac > 65535) + { + yfrac -= 65535; + from += origwidth; + } + + from += ywhole*origwidth; + to += WGT_SYS.xres - endwidth; + } + } +}