/*
|
/*
|
* Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Portions Copyright (c) 1991 David I. Bell
|
* Portions Copyright (c) 1991 David I. Bell
|
* Permission is granted to use, distribute, or modify this source,
|
* Permission is granted to use, distribute, or modify this source,
|
* provided that this copyright notice remains intact.
|
* provided that this copyright notice remains intact.
|
*
|
*
|
* Device-independent mid level drawing and color routines.
|
* Device-independent mid level drawing and color routines.
|
*
|
*
|
* These routines do the necessary range checking, clipping, and cursor
|
* These routines do the necessary range checking, clipping, and cursor
|
* overwriting checks, and then call the lower level device dependent
|
* overwriting checks, and then call the lower level device dependent
|
* routines to actually do the drawing. The lower level routines are
|
* routines to actually do the drawing. The lower level routines are
|
* only called when it is known that all the pixels to be drawn are
|
* only called when it is known that all the pixels to be drawn are
|
* within the device area and are visible.
|
* within the device area and are visible.
|
*/
|
*/
|
/*#define NDEBUG*/
|
/*#define NDEBUG*/
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <assert.h>
|
#include <assert.h>
|
#include "device.h"
|
#include "device.h"
|
|
|
extern MWPIXELVAL gr_foreground; /* current foreground color */
|
extern MWPIXELVAL gr_foreground; /* current foreground color */
|
extern MWPIXELVAL gr_background; /* current background color */
|
extern MWPIXELVAL gr_background; /* current background color */
|
extern MWBOOL gr_usebg; /* TRUE if background drawn in pixmaps */
|
extern MWBOOL gr_usebg; /* TRUE if background drawn in pixmaps */
|
extern int gr_mode; /* drawing mode */
|
extern int gr_mode; /* drawing mode */
|
extern MWPALENTRY gr_palette[256]; /* current palette*/
|
extern MWPALENTRY gr_palette[256]; /* current palette*/
|
extern int gr_firstuserpalentry;/* first user-changable palette entry*/
|
extern int gr_firstuserpalentry;/* first user-changable palette entry*/
|
extern int gr_nextpalentry; /* next available palette entry*/
|
extern int gr_nextpalentry; /* next available palette entry*/
|
|
|
/*static*/ void drawpoint(PSD psd,MWCOORD x, MWCOORD y);
|
/*static*/ void drawpoint(PSD psd,MWCOORD x, MWCOORD y);
|
/*static*/ void drawrow(PSD psd,MWCOORD x1,MWCOORD x2,MWCOORD y);
|
/*static*/ void drawrow(PSD psd,MWCOORD x1,MWCOORD x2,MWCOORD y);
|
static void drawcol(PSD psd,MWCOORD x,MWCOORD y1,MWCOORD y2);
|
static void drawcol(PSD psd,MWCOORD x,MWCOORD y1,MWCOORD y2);
|
|
|
/*
|
/*
|
* Set the drawing mode for future calls.
|
* Set the drawing mode for future calls.
|
*/
|
*/
|
int
|
int
|
GdSetMode(int mode)
|
GdSetMode(int mode)
|
{
|
{
|
int oldmode = gr_mode;
|
int oldmode = gr_mode;
|
|
|
gr_mode = mode;
|
gr_mode = mode;
|
return oldmode;
|
return oldmode;
|
}
|
}
|
|
|
/*
|
/*
|
* Set whether or not the background is used for drawing pixmaps and text.
|
* Set whether or not the background is used for drawing pixmaps and text.
|
*/
|
*/
|
MWBOOL
|
MWBOOL
|
GdSetUseBackground(MWBOOL flag)
|
GdSetUseBackground(MWBOOL flag)
|
{
|
{
|
MWBOOL oldusebg = gr_usebg;
|
MWBOOL oldusebg = gr_usebg;
|
|
|
gr_usebg = flag;
|
gr_usebg = flag;
|
return oldusebg;
|
return oldusebg;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the foreground color for drawing.
|
* Set the foreground color for drawing.
|
*/
|
*/
|
MWPIXELVAL
|
MWPIXELVAL
|
GdSetForeground(MWPIXELVAL fg)
|
GdSetForeground(MWPIXELVAL fg)
|
{
|
{
|
MWPIXELVAL oldfg = gr_foreground;
|
MWPIXELVAL oldfg = gr_foreground;
|
|
|
gr_foreground = fg;
|
gr_foreground = fg;
|
return oldfg;
|
return oldfg;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the background color for bitmap and text backgrounds.
|
* Set the background color for bitmap and text backgrounds.
|
*/
|
*/
|
MWPIXELVAL
|
MWPIXELVAL
|
GdSetBackground(MWPIXELVAL bg)
|
GdSetBackground(MWPIXELVAL bg)
|
{
|
{
|
MWPIXELVAL oldbg = gr_background;
|
MWPIXELVAL oldbg = gr_background;
|
|
|
gr_background = bg;
|
gr_background = bg;
|
return oldbg;
|
return oldbg;
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a point using the current clipping region and foreground color.
|
* Draw a point using the current clipping region and foreground color.
|
*/
|
*/
|
void
|
void
|
GdPoint(PSD psd, MWCOORD x, MWCOORD y)
|
GdPoint(PSD psd, MWCOORD x, MWCOORD y)
|
{
|
{
|
if (GdClipPoint(psd, x, y)) {
|
if (GdClipPoint(psd, x, y)) {
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw an arbitrary line using the current clipping region and foreground color
|
* Draw an arbitrary line using the current clipping region and foreground color
|
* If bDrawLastPoint is FALSE, draw up to but not including point x2, y2.
|
* If bDrawLastPoint is FALSE, draw up to but not including point x2, y2.
|
*
|
*
|
* This routine is the only routine that adjusts coordinates for supporting
|
* This routine is the only routine that adjusts coordinates for supporting
|
* two different types of upper levels, those that draw the last point
|
* two different types of upper levels, those that draw the last point
|
* in a line, and those that draw up to the last point. All other local
|
* in a line, and those that draw up to the last point. All other local
|
* routines draw the last point. This gives this routine a bit more overhead,
|
* routines draw the last point. This gives this routine a bit more overhead,
|
* but keeps overall complexity down.
|
* but keeps overall complexity down.
|
*/
|
*/
|
void
|
void
|
GdLine(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2,
|
GdLine(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2,
|
MWBOOL bDrawLastPoint)
|
MWBOOL bDrawLastPoint)
|
{
|
{
|
int xdelta; /* width of rectangle around line */
|
int xdelta; /* width of rectangle around line */
|
int ydelta; /* height of rectangle around line */
|
int ydelta; /* height of rectangle around line */
|
int xinc; /* increment for moving x coordinate */
|
int xinc; /* increment for moving x coordinate */
|
int yinc; /* increment for moving y coordinate */
|
int yinc; /* increment for moving y coordinate */
|
int rem; /* current remainder */
|
int rem; /* current remainder */
|
MWCOORD temp;
|
MWCOORD temp;
|
|
|
/* See if the line is horizontal or vertical. If so, then call
|
/* See if the line is horizontal or vertical. If so, then call
|
* special routines.
|
* special routines.
|
*/
|
*/
|
if (y1 == y2) {
|
if (y1 == y2) {
|
/*
|
/*
|
* Adjust coordinates if not drawing last point. Tricky.
|
* Adjust coordinates if not drawing last point. Tricky.
|
*/
|
*/
|
if(!bDrawLastPoint) {
|
if(!bDrawLastPoint) {
|
if (x1 > x2) {
|
if (x1 > x2) {
|
temp = x1;
|
temp = x1;
|
x1 = x2 + 1;
|
x1 = x2 + 1;
|
x2 = temp;
|
x2 = temp;
|
} else
|
} else
|
--x2;
|
--x2;
|
}
|
}
|
|
|
/* call faster line drawing routine*/
|
/* call faster line drawing routine*/
|
drawrow(psd, x1, x2, y1);
|
drawrow(psd, x1, x2, y1);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
return;
|
return;
|
}
|
}
|
if (x1 == x2) {
|
if (x1 == x2) {
|
/*
|
/*
|
* Adjust coordinates if not drawing last point. Tricky.
|
* Adjust coordinates if not drawing last point. Tricky.
|
*/
|
*/
|
if(!bDrawLastPoint) {
|
if(!bDrawLastPoint) {
|
if (y1 > y2) {
|
if (y1 > y2) {
|
temp = y1;
|
temp = y1;
|
y1 = y2 + 1;
|
y1 = y2 + 1;
|
y2 = temp;
|
y2 = temp;
|
} else
|
} else
|
--y2;
|
--y2;
|
}
|
}
|
|
|
/* call faster line drawing routine*/
|
/* call faster line drawing routine*/
|
drawcol(psd, x1, y1, y2);
|
drawcol(psd, x1, y1, y2);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
return;
|
return;
|
}
|
}
|
|
|
/* See if the line is either totally visible or totally invisible. If
|
/* See if the line is either totally visible or totally invisible. If
|
* so, then the line drawing is easy.
|
* so, then the line drawing is easy.
|
*/
|
*/
|
switch (GdClipArea(psd, x1, y1, x2, y2)) {
|
switch (GdClipArea(psd, x1, y1, x2, y2)) {
|
case CLIP_VISIBLE:
|
case CLIP_VISIBLE:
|
/*
|
/*
|
* For size considerations, there's no low-level bresenham
|
* For size considerations, there's no low-level bresenham
|
* line draw, so we've got to draw all non-vertical
|
* line draw, so we've got to draw all non-vertical
|
* and non-horizontal lines with per-point
|
* and non-horizontal lines with per-point
|
* clipping for the time being
|
* clipping for the time being
|
psd->Line(psd, x1, y1, x2, y2, gr_foreground);
|
psd->Line(psd, x1, y1, x2, y2, gr_foreground);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
return;
|
return;
|
*/
|
*/
|
break;
|
break;
|
case CLIP_INVISIBLE:
|
case CLIP_INVISIBLE:
|
return;
|
return;
|
}
|
}
|
|
|
/* The line may be partially obscured. Do the draw line algorithm
|
/* The line may be partially obscured. Do the draw line algorithm
|
* checking each point against the clipping regions.
|
* checking each point against the clipping regions.
|
*/
|
*/
|
xdelta = x2 - x1;
|
xdelta = x2 - x1;
|
ydelta = y2 - y1;
|
ydelta = y2 - y1;
|
if (xdelta < 0) xdelta = -xdelta;
|
if (xdelta < 0) xdelta = -xdelta;
|
if (ydelta < 0) ydelta = -ydelta;
|
if (ydelta < 0) ydelta = -ydelta;
|
xinc = (x2 > x1) ? 1 : -1;
|
xinc = (x2 > x1) ? 1 : -1;
|
yinc = (y2 > y1) ? 1 : -1;
|
yinc = (y2 > y1) ? 1 : -1;
|
if (GdClipPoint(psd, x1, y1))
|
if (GdClipPoint(psd, x1, y1))
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
if (xdelta >= ydelta) {
|
if (xdelta >= ydelta) {
|
rem = xdelta / 2;
|
rem = xdelta / 2;
|
for(;;) {
|
for(;;) {
|
if(!bDrawLastPoint && x1 == x2)
|
if(!bDrawLastPoint && x1 == x2)
|
break;
|
break;
|
x1 += xinc;
|
x1 += xinc;
|
rem += ydelta;
|
rem += ydelta;
|
if (rem >= xdelta) {
|
if (rem >= xdelta) {
|
rem -= xdelta;
|
rem -= xdelta;
|
y1 += yinc;
|
y1 += yinc;
|
}
|
}
|
if (GdClipPoint(psd, x1, y1))
|
if (GdClipPoint(psd, x1, y1))
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
if(bDrawLastPoint && x1 == x2)
|
if(bDrawLastPoint && x1 == x2)
|
break;
|
break;
|
}
|
}
|
} else {
|
} else {
|
rem = ydelta / 2;
|
rem = ydelta / 2;
|
for(;;) {
|
for(;;) {
|
if(!bDrawLastPoint && y1 == y2)
|
if(!bDrawLastPoint && y1 == y2)
|
break;
|
break;
|
y1 += yinc;
|
y1 += yinc;
|
rem += xdelta;
|
rem += xdelta;
|
if (rem >= ydelta) {
|
if (rem >= ydelta) {
|
rem -= ydelta;
|
rem -= ydelta;
|
x1 += xinc;
|
x1 += xinc;
|
}
|
}
|
if (GdClipPoint(psd, x1, y1))
|
if (GdClipPoint(psd, x1, y1))
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
psd->DrawPixel(psd, x1, y1, gr_foreground);
|
if(bDrawLastPoint && y1 == y2)
|
if(bDrawLastPoint && y1 == y2)
|
break;
|
break;
|
}
|
}
|
}
|
}
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/* Draw a point in the foreground color, applying clipping if necessary*/
|
/* Draw a point in the foreground color, applying clipping if necessary*/
|
/*static*/ void
|
/*static*/ void
|
drawpoint(PSD psd, MWCOORD x, MWCOORD y)
|
drawpoint(PSD psd, MWCOORD x, MWCOORD y)
|
{
|
{
|
if (GdClipPoint(psd, x, y))
|
if (GdClipPoint(psd, x, y))
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
}
|
}
|
|
|
/* Draw a horizontal line from x1 to and including x2 in the
|
/* Draw a horizontal line from x1 to and including x2 in the
|
* foreground color, applying clipping if necessary.
|
* foreground color, applying clipping if necessary.
|
*/
|
*/
|
/*static*/ void
|
/*static*/ void
|
drawrow(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y)
|
drawrow(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y)
|
{
|
{
|
MWCOORD temp;
|
MWCOORD temp;
|
|
|
/* reverse endpoints if necessary*/
|
/* reverse endpoints if necessary*/
|
if (x1 > x2) {
|
if (x1 > x2) {
|
temp = x1;
|
temp = x1;
|
x1 = x2;
|
x1 = x2;
|
x2 = temp;
|
x2 = temp;
|
}
|
}
|
|
|
/* clip to physical device*/
|
/* clip to physical device*/
|
if (x1 < 0)
|
if (x1 < 0)
|
x1 = 0;
|
x1 = 0;
|
if (x2 >= psd->xvirtres)
|
if (x2 >= psd->xvirtres)
|
x2 = psd->xvirtres - 1;
|
x2 = psd->xvirtres - 1;
|
|
|
/* check cursor intersect once for whole line*/
|
/* check cursor intersect once for whole line*/
|
GdCheckCursor(psd, x1, y, x2, y);
|
GdCheckCursor(psd, x1, y, x2, y);
|
|
|
while (x1 <= x2) {
|
while (x1 <= x2) {
|
if (GdClipPoint(psd, x1, y)) {
|
if (GdClipPoint(psd, x1, y)) {
|
temp = MWMIN(clipmaxx, x2);
|
temp = MWMIN(clipmaxx, x2);
|
psd->DrawHorzLine(psd, x1, temp, y, gr_foreground);
|
psd->DrawHorzLine(psd, x1, temp, y, gr_foreground);
|
} else
|
} else
|
temp = MWMIN(clipmaxx, x2);
|
temp = MWMIN(clipmaxx, x2);
|
x1 = temp + 1;
|
x1 = temp + 1;
|
}
|
}
|
}
|
}
|
|
|
/* Draw a vertical line from y1 to and including y2 in the
|
/* Draw a vertical line from y1 to and including y2 in the
|
* foreground color, applying clipping if necessary.
|
* foreground color, applying clipping if necessary.
|
*/
|
*/
|
static void
|
static void
|
drawcol(PSD psd, MWCOORD x,MWCOORD y1,MWCOORD y2)
|
drawcol(PSD psd, MWCOORD x,MWCOORD y1,MWCOORD y2)
|
{
|
{
|
MWCOORD temp;
|
MWCOORD temp;
|
|
|
/* reverse endpoints if necessary*/
|
/* reverse endpoints if necessary*/
|
if (y1 > y2) {
|
if (y1 > y2) {
|
temp = y1;
|
temp = y1;
|
y1 = y2;
|
y1 = y2;
|
y2 = temp;
|
y2 = temp;
|
}
|
}
|
|
|
/* clip to physical device*/
|
/* clip to physical device*/
|
if (y1 < 0)
|
if (y1 < 0)
|
y1 = 0;
|
y1 = 0;
|
if (y2 >= psd->yvirtres)
|
if (y2 >= psd->yvirtres)
|
y2 = psd->yvirtres - 1;
|
y2 = psd->yvirtres - 1;
|
|
|
/* check cursor intersect once for whole line*/
|
/* check cursor intersect once for whole line*/
|
GdCheckCursor(psd, x, y1, x, y2);
|
GdCheckCursor(psd, x, y1, x, y2);
|
|
|
while (y1 <= y2) {
|
while (y1 <= y2) {
|
if (GdClipPoint(psd, x, y1)) {
|
if (GdClipPoint(psd, x, y1)) {
|
temp = MWMIN(clipmaxy, y2);
|
temp = MWMIN(clipmaxy, y2);
|
psd->DrawVertLine(psd, x, y1, temp, gr_foreground);
|
psd->DrawVertLine(psd, x, y1, temp, gr_foreground);
|
} else
|
} else
|
temp = MWMIN(clipmaxy, y2);
|
temp = MWMIN(clipmaxy, y2);
|
y1 = temp + 1;
|
y1 = temp + 1;
|
}
|
}
|
}
|
}
|
|
|
/* Draw a rectangle in the foreground color, applying clipping if necessary.
|
/* Draw a rectangle in the foreground color, applying clipping if necessary.
|
* This is careful to not draw points multiple times in case the rectangle
|
* This is careful to not draw points multiple times in case the rectangle
|
* is being drawn using XOR.
|
* is being drawn using XOR.
|
*/
|
*/
|
void
|
void
|
GdRect(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height)
|
GdRect(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height)
|
{
|
{
|
MWCOORD maxx;
|
MWCOORD maxx;
|
MWCOORD maxy;
|
MWCOORD maxy;
|
|
|
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
return;
|
return;
|
maxx = x + width - 1;
|
maxx = x + width - 1;
|
maxy = y + height - 1;
|
maxy = y + height - 1;
|
drawrow(psd, x, maxx, y);
|
drawrow(psd, x, maxx, y);
|
if (height > 1)
|
if (height > 1)
|
drawrow(psd, x, maxx, maxy);
|
drawrow(psd, x, maxx, maxy);
|
if (height < 3)
|
if (height < 3)
|
return;
|
return;
|
y++;
|
y++;
|
maxy--;
|
maxy--;
|
drawcol(psd, x, y, maxy);
|
drawcol(psd, x, y, maxy);
|
if (width > 1)
|
if (width > 1)
|
drawcol(psd, maxx, y, maxy);
|
drawcol(psd, maxx, y, maxy);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/* Draw a filled in rectangle in the foreground color, applying
|
/* Draw a filled in rectangle in the foreground color, applying
|
* clipping if necessary.
|
* clipping if necessary.
|
*/
|
*/
|
void
|
void
|
GdFillRect(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD width, MWCOORD height)
|
GdFillRect(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD width, MWCOORD height)
|
{
|
{
|
MWCOORD x2 = x1+width-1;
|
MWCOORD x2 = x1+width-1;
|
MWCOORD y2 = y1+height-1;
|
MWCOORD y2 = y1+height-1;
|
|
|
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
return;
|
return;
|
|
|
/* See if the rectangle is either totally visible or totally
|
/* See if the rectangle is either totally visible or totally
|
* invisible. If so, then the rectangle drawing is easy.
|
* invisible. If so, then the rectangle drawing is easy.
|
*/
|
*/
|
switch (GdClipArea(psd, x1, y1, x2, y2)) {
|
switch (GdClipArea(psd, x1, y1, x2, y2)) {
|
case CLIP_VISIBLE:
|
case CLIP_VISIBLE:
|
psd->FillRect(psd, x1, y1, x2, y2, gr_foreground);
|
psd->FillRect(psd, x1, y1, x2, y2, gr_foreground);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
return;
|
return;
|
|
|
case CLIP_INVISIBLE:
|
case CLIP_INVISIBLE:
|
return;
|
return;
|
}
|
}
|
|
|
/* The rectangle may be partially obstructed. So do it line by line. */
|
/* The rectangle may be partially obstructed. So do it line by line. */
|
while (y1 <= y2)
|
while (y1 <= y2)
|
drawrow(psd, x1, x2, y1++);
|
drawrow(psd, x1, x2, y1++);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a rectangular area using the current clipping region and the
|
* Draw a rectangular area using the current clipping region and the
|
* specified bit map. This differs from rectangle drawing in that the
|
* specified bit map. This differs from rectangle drawing in that the
|
* rectangle is drawn using the foreground color and possibly the background
|
* rectangle is drawn using the foreground color and possibly the background
|
* color as determined by the bit map. Each row of bits is aligned to the
|
* color as determined by the bit map. Each row of bits is aligned to the
|
* next bitmap word boundary (so there is padding at the end of the row).
|
* next bitmap word boundary (so there is padding at the end of the row).
|
* The background bit values are only written if the gr_usebg flag
|
* The background bit values are only written if the gr_usebg flag
|
* is set.
|
* is set.
|
*/
|
*/
|
void
|
void
|
GdBitmap(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
GdBitmap(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
MWIMAGEBITS *imagebits)
|
MWIMAGEBITS *imagebits)
|
{
|
{
|
MWCOORD minx;
|
MWCOORD minx;
|
MWCOORD maxx;
|
MWCOORD maxx;
|
MWPIXELVAL savecolor; /* saved foreground color */
|
MWPIXELVAL savecolor; /* saved foreground color */
|
MWIMAGEBITS bitvalue = 0; /* bitmap word value */
|
MWIMAGEBITS bitvalue = 0; /* bitmap word value */
|
int bitcount; /* number of bits left in bitmap word */
|
int bitcount; /* number of bits left in bitmap word */
|
|
|
switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
|
switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
|
case CLIP_VISIBLE:
|
case CLIP_VISIBLE:
|
/*
|
/*
|
* For size considerations, there's no low-level bitmap
|
* For size considerations, there's no low-level bitmap
|
* draw so we've got to draw everything with per-point
|
* draw so we've got to draw everything with per-point
|
* clipping for the time being.
|
* clipping for the time being.
|
if (gr_usebg)
|
if (gr_usebg)
|
psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
|
psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
|
gr_background);
|
gr_background);
|
psd->DrawBitmap(psd, x, y, width, height, imagebits, gr_foreground);
|
psd->DrawBitmap(psd, x, y, width, height, imagebits, gr_foreground);
|
return;
|
return;
|
*/
|
*/
|
break;
|
break;
|
|
|
case CLIP_INVISIBLE:
|
case CLIP_INVISIBLE:
|
return;
|
return;
|
}
|
}
|
|
|
/* The rectangle is partially visible, so must do clipping. First
|
/* The rectangle is partially visible, so must do clipping. First
|
* fill a rectangle in the background color if necessary.
|
* fill a rectangle in the background color if necessary.
|
*/
|
*/
|
if (gr_usebg) {
|
if (gr_usebg) {
|
savecolor = gr_foreground;
|
savecolor = gr_foreground;
|
gr_foreground = gr_background;
|
gr_foreground = gr_background;
|
/* note: change to fillrect*/
|
/* note: change to fillrect*/
|
GdFillRect(psd, x, y, width, height);
|
GdFillRect(psd, x, y, width, height);
|
gr_foreground = savecolor;
|
gr_foreground = savecolor;
|
}
|
}
|
minx = x;
|
minx = x;
|
maxx = x + width - 1;
|
maxx = x + width - 1;
|
bitcount = 0;
|
bitcount = 0;
|
while (height > 0) {
|
while (height > 0) {
|
if (bitcount <= 0) {
|
if (bitcount <= 0) {
|
bitcount = MWIMAGE_BITSPERIMAGE;
|
bitcount = MWIMAGE_BITSPERIMAGE;
|
bitvalue = *imagebits++;
|
bitvalue = *imagebits++;
|
}
|
}
|
if (MWIMAGE_TESTBIT(bitvalue) && GdClipPoint(psd, x, y))
|
if (MWIMAGE_TESTBIT(bitvalue) && GdClipPoint(psd, x, y))
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
psd->DrawPixel(psd, x, y, gr_foreground);
|
bitvalue = MWIMAGE_SHIFTBIT(bitvalue);
|
bitvalue = MWIMAGE_SHIFTBIT(bitvalue);
|
bitcount--;
|
bitcount--;
|
if (x++ == maxx) {
|
if (x++ == maxx) {
|
x = minx;
|
x = minx;
|
y++;
|
y++;
|
height--;
|
height--;
|
bitcount = 0;
|
bitcount = 0;
|
}
|
}
|
}
|
}
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/*
|
/*
|
* Return true if color is in palette
|
* Return true if color is in palette
|
*/
|
*/
|
MWBOOL
|
MWBOOL
|
GdColorInPalette(MWCOLORVAL cr,MWPALENTRY *palette,int palsize)
|
GdColorInPalette(MWCOLORVAL cr,MWPALENTRY *palette,int palsize)
|
{
|
{
|
int i;
|
int i;
|
|
|
for(i=0; i<palsize; ++i)
|
for(i=0; i<palsize; ++i)
|
if(GETPALENTRY(palette, i) == cr)
|
if(GETPALENTRY(palette, i) == cr)
|
return TRUE;
|
return TRUE;
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
/*
|
/*
|
* Create a MWPIXELVAL conversion table between the passed palette
|
* Create a MWPIXELVAL conversion table between the passed palette
|
* and the in-use palette. The system palette is loaded/merged according
|
* and the in-use palette. The system palette is loaded/merged according
|
* to fLoadType.
|
* to fLoadType.
|
*/
|
*/
|
void
|
void
|
GdMakePaletteConversionTable(PSD psd,MWPALENTRY *palette,int palsize,
|
GdMakePaletteConversionTable(PSD psd,MWPALENTRY *palette,int palsize,
|
MWPIXELVAL *convtable,int fLoadType)
|
MWPIXELVAL *convtable,int fLoadType)
|
{
|
{
|
int i;
|
int i;
|
MWCOLORVAL cr;
|
MWCOLORVAL cr;
|
int newsize, nextentry;
|
int newsize, nextentry;
|
MWPALENTRY newpal[256];
|
MWPALENTRY newpal[256];
|
|
|
/*
|
/*
|
* Check for load palette completely, or add colors
|
* Check for load palette completely, or add colors
|
* from passed palette to system palette until full.
|
* from passed palette to system palette until full.
|
*/
|
*/
|
if(psd->pixtype == MWPF_PALETTE) {
|
if(psd->pixtype == MWPF_PALETTE) {
|
switch(fLoadType) {
|
switch(fLoadType) {
|
case LOADPALETTE:
|
case LOADPALETTE:
|
/* Load palette from beginning with image's palette.
|
/* Load palette from beginning with image's palette.
|
* First palette entries are Microwindows colors
|
* First palette entries are Microwindows colors
|
* and not changed.
|
* and not changed.
|
*/
|
*/
|
GdSetPalette(psd, gr_firstuserpalentry, palsize, palette);
|
GdSetPalette(psd, gr_firstuserpalentry, palsize, palette);
|
break;
|
break;
|
|
|
case MERGEPALETTE:
|
case MERGEPALETTE:
|
/* get system palette*/
|
/* get system palette*/
|
for(i=0; i<(int)psd->ncolors; ++i)
|
for(i=0; i<(int)psd->ncolors; ++i)
|
newpal[i] = gr_palette[i];
|
newpal[i] = gr_palette[i];
|
|
|
/* merge passed palette into system palette*/
|
/* merge passed palette into system palette*/
|
newsize = 0;
|
newsize = 0;
|
nextentry = gr_nextpalentry;
|
nextentry = gr_nextpalentry;
|
|
|
/* if color missing and there's room, add it*/
|
/* if color missing and there's room, add it*/
|
for(i=0; i<palsize && nextentry < (int)psd->ncolors; ++i) {
|
for(i=0; i<palsize && nextentry < (int)psd->ncolors; ++i) {
|
cr = GETPALENTRY(palette, i);
|
cr = GETPALENTRY(palette, i);
|
if(!GdColorInPalette(cr, newpal, nextentry)) {
|
if(!GdColorInPalette(cr, newpal, nextentry)) {
|
newpal[nextentry++] = palette[i];
|
newpal[nextentry++] = palette[i];
|
++newsize;
|
++newsize;
|
}
|
}
|
}
|
}
|
|
|
/* set the new palette if any color was added*/
|
/* set the new palette if any color was added*/
|
if(newsize) {
|
if(newsize) {
|
GdSetPalette(psd, gr_nextpalentry, newsize,
|
GdSetPalette(psd, gr_nextpalentry, newsize,
|
&newpal[gr_nextpalentry]);
|
&newpal[gr_nextpalentry]);
|
gr_nextpalentry += newsize;
|
gr_nextpalentry += newsize;
|
}
|
}
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Build conversion table from inuse system palette and
|
* Build conversion table from inuse system palette and
|
* passed palette. This will load RGB values directly
|
* passed palette. This will load RGB values directly
|
* if running truecolor, otherwise it will find the
|
* if running truecolor, otherwise it will find the
|
* nearest color from the inuse palette.
|
* nearest color from the inuse palette.
|
* FIXME: tag the conversion table to the bitmap image
|
* FIXME: tag the conversion table to the bitmap image
|
*/
|
*/
|
for(i=0; i<palsize; ++i) {
|
for(i=0; i<palsize; ++i) {
|
cr = GETPALENTRY(palette, i);
|
cr = GETPALENTRY(palette, i);
|
convtable[i] = GdFindColor(cr);
|
convtable[i] = GdFindColor(cr);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a color bitmap image in 1, 4, 8, 24 or 32 bits per pixel. The
|
* Draw a color bitmap image in 1, 4, 8, 24 or 32 bits per pixel. The
|
* Microwindows color image format is DWORD padded bytes, with
|
* Microwindows color image format is DWORD padded bytes, with
|
* the upper bits corresponding to the left side (identical to
|
* the upper bits corresponding to the left side (identical to
|
* the MS Windows format). This format is currently different
|
* the MS Windows format). This format is currently different
|
* than the MWIMAGEBITS format, which uses word-padded bits
|
* than the MWIMAGEBITS format, which uses word-padded bits
|
* for monochrome display only, where the upper bits in the word
|
* for monochrome display only, where the upper bits in the word
|
* correspond with the left side.
|
* correspond with the left side.
|
*/
|
*/
|
void
|
void
|
GdDrawImage(PSD psd, MWCOORD x, MWCOORD y, PMWIMAGEHDR pimage)
|
GdDrawImage(PSD psd, MWCOORD x, MWCOORD y, PMWIMAGEHDR pimage)
|
{
|
{
|
MWCOORD minx;
|
MWCOORD minx;
|
MWCOORD maxx;
|
MWCOORD maxx;
|
MWUCHAR bitvalue = 0;
|
MWUCHAR bitvalue = 0;
|
int bitcount;
|
int bitcount;
|
MWUCHAR *imagebits;
|
MWUCHAR *imagebits;
|
MWCOORD height, width;
|
MWCOORD height, width;
|
MWPIXELVAL pixel;
|
MWPIXELVAL pixel;
|
int clip;
|
int clip;
|
int extra, linesize;
|
int extra, linesize;
|
int rgborder;
|
int rgborder;
|
MWCOLORVAL cr;
|
MWCOLORVAL cr;
|
MWCOORD yoff;
|
MWCOORD yoff;
|
unsigned long transcolor;
|
unsigned long transcolor;
|
MWPIXELVAL convtable[256];
|
MWPIXELVAL convtable[256];
|
|
|
height = pimage->height;
|
height = pimage->height;
|
width = pimage->width;
|
width = pimage->width;
|
|
|
/* determine if entire image is clipped out, save clipresult for later*/
|
/* determine if entire image is clipped out, save clipresult for later*/
|
clip = GdClipArea(psd, x, y, x + width - 1, y + height - 1);
|
clip = GdClipArea(psd, x, y, x + width - 1, y + height - 1);
|
if(clip == CLIP_INVISIBLE)
|
if(clip == CLIP_INVISIBLE)
|
return;
|
return;
|
|
|
transcolor = pimage->transcolor;
|
transcolor = pimage->transcolor;
|
|
|
/*
|
/*
|
* Merge the images's palette and build a palette index conversion table.
|
* Merge the images's palette and build a palette index conversion table.
|
*/
|
*/
|
if (pimage->bpp <= 8) {
|
if (pimage->bpp <= 8) {
|
if(!pimage->palette) {
|
if(!pimage->palette) {
|
/* for jpeg's without a palette*/
|
/* for jpeg's without a palette*/
|
for(yoff=0; yoff<pimage->palsize; ++yoff)
|
for(yoff=0; yoff<pimage->palsize; ++yoff)
|
convtable[yoff] = yoff;
|
convtable[yoff] = yoff;
|
} else GdMakePaletteConversionTable(psd, pimage->palette,
|
} else GdMakePaletteConversionTable(psd, pimage->palette,
|
pimage->palsize, convtable, MERGEPALETTE);
|
pimage->palsize, convtable, MERGEPALETTE);
|
|
|
/* The following is no longer used. One reason is that it required */
|
/* The following is no longer used. One reason is that it required */
|
/* the transparent color to be unique, which was unnessecary */
|
/* the transparent color to be unique, which was unnessecary */
|
|
|
/* convert transcolor to converted palette index for speed*/
|
/* convert transcolor to converted palette index for speed*/
|
/* if (transcolor != -1L)
|
/* if (transcolor != -1L)
|
transcolor = (unsigned long) convtable[transcolor]; */
|
transcolor = (unsigned long) convtable[transcolor]; */
|
}
|
}
|
|
|
minx = x;
|
minx = x;
|
maxx = x + width - 1;
|
maxx = x + width - 1;
|
imagebits = pimage->imagebits;
|
imagebits = pimage->imagebits;
|
|
|
/* check for bottom-up image*/
|
/* check for bottom-up image*/
|
if(pimage->compression & MWIMAGE_UPSIDEDOWN) {
|
if(pimage->compression & MWIMAGE_UPSIDEDOWN) {
|
y += height - 1;
|
y += height - 1;
|
yoff = -1;
|
yoff = -1;
|
} else
|
} else
|
yoff = 1;
|
yoff = 1;
|
|
|
#define PIX2BYTES(n) (((n)+7)/8)
|
#define PIX2BYTES(n) (((n)+7)/8)
|
/* imagebits are dword aligned*/
|
/* imagebits are dword aligned*/
|
switch(pimage->bpp) {
|
switch(pimage->bpp) {
|
default:
|
default:
|
case 8:
|
case 8:
|
linesize = width;
|
linesize = width;
|
break;
|
break;
|
case 32:
|
case 32:
|
linesize = width*4;
|
linesize = width*4;
|
break;
|
break;
|
case 24:
|
case 24:
|
linesize = width*3;
|
linesize = width*3;
|
break;
|
break;
|
case 4:
|
case 4:
|
linesize = PIX2BYTES(width<<2);
|
linesize = PIX2BYTES(width<<2);
|
break;
|
break;
|
case 1:
|
case 1:
|
linesize = PIX2BYTES(width);
|
linesize = PIX2BYTES(width);
|
break;
|
break;
|
}
|
}
|
extra = pimage->pitch - linesize;
|
extra = pimage->pitch - linesize;
|
|
|
/* 24bpp RGB rather than BGR byte order?*/
|
/* 24bpp RGB rather than BGR byte order?*/
|
rgborder = pimage->compression & MWIMAGE_RGB;
|
rgborder = pimage->compression & MWIMAGE_RGB;
|
|
|
bitcount = 0;
|
bitcount = 0;
|
while(height > 0) {
|
while(height > 0) {
|
unsigned long trans = 0;
|
unsigned long trans = 0;
|
|
|
if (bitcount <= 0) {
|
if (bitcount <= 0) {
|
bitcount = sizeof(MWUCHAR) * 8;
|
bitcount = sizeof(MWUCHAR) * 8;
|
bitvalue = *imagebits++;
|
bitvalue = *imagebits++;
|
}
|
}
|
switch(pimage->bpp) {
|
switch(pimage->bpp) {
|
case 24:
|
case 24:
|
case 32:
|
case 32:
|
cr = rgborder? MWRGB(bitvalue, imagebits[0], imagebits[1]):
|
cr = rgborder? MWRGB(bitvalue, imagebits[0], imagebits[1]):
|
MWRGB(imagebits[1], imagebits[0], bitvalue);
|
MWRGB(imagebits[1], imagebits[0], bitvalue);
|
|
|
/* Include the upper bits for transcolor stuff */
|
/* Include the upper bits for transcolor stuff */
|
if (imagebits[2]) /* FIXME: 24bpp error*/
|
if (imagebits[2]) /* FIXME: 24bpp error*/
|
trans = cr | 0x01000000L;
|
trans = cr | 0x01000000L;
|
|
|
if (pimage->bpp == 32)
|
if (pimage->bpp == 32)
|
imagebits += 3;
|
imagebits += 3;
|
else imagebits += 2;
|
else imagebits += 2;
|
bitcount = 0;
|
bitcount = 0;
|
|
|
/* handle transparent color*/
|
/* handle transparent color*/
|
if (transcolor == trans)
|
if (transcolor == trans)
|
goto next;
|
goto next;
|
|
|
switch(psd->pixtype) {
|
switch(psd->pixtype) {
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
default:
|
default:
|
pixel = GdFindColor(cr);
|
pixel = GdFindColor(cr);
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
pixel = COLOR2PIXEL888(cr);
|
pixel = COLOR2PIXEL888(cr);
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
pixel = COLOR2PIXEL565(cr);
|
pixel = COLOR2PIXEL565(cr);
|
break;
|
break;
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
pixel = COLOR2PIXEL555(cr);
|
pixel = COLOR2PIXEL555(cr);
|
break;
|
break;
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
pixel = COLOR2PIXEL332(cr);
|
pixel = COLOR2PIXEL332(cr);
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
default:
|
default:
|
case 8:
|
case 8:
|
bitcount = 0;
|
bitcount = 0;
|
if (bitvalue == transcolor)
|
if (bitvalue == transcolor)
|
goto next;
|
goto next;
|
|
|
pixel = convtable[bitvalue];
|
pixel = convtable[bitvalue];
|
break;
|
break;
|
case 4:
|
case 4:
|
if (((bitvalue & 0xf0) >> 4) == transcolor) {
|
if (((bitvalue & 0xf0) >> 4) == transcolor) {
|
bitvalue <<= 4;
|
bitvalue <<= 4;
|
bitcount -= 4;
|
bitcount -= 4;
|
goto next;
|
goto next;
|
}
|
}
|
|
|
pixel = convtable[(bitvalue & 0xf0) >> 4];
|
pixel = convtable[(bitvalue & 0xf0) >> 4];
|
bitvalue <<= 4;
|
bitvalue <<= 4;
|
bitcount -= 4;
|
bitcount -= 4;
|
break;
|
break;
|
case 1:
|
case 1:
|
--bitcount;
|
--bitcount;
|
if (((bitvalue & 0x80) ? 1 : 0) == transcolor) {
|
if (((bitvalue & 0x80) ? 1 : 0) == transcolor) {
|
bitvalue <<= 1;
|
bitvalue <<= 1;
|
goto next;
|
goto next;
|
}
|
}
|
|
|
pixel = convtable[(bitvalue & 0x80)? 1: 0];
|
pixel = convtable[(bitvalue & 0x80)? 1: 0];
|
bitvalue <<= 1;
|
bitvalue <<= 1;
|
break;
|
break;
|
}
|
}
|
|
|
/* if((unsigned long)pixel != transcolor &&*/
|
/* if((unsigned long)pixel != transcolor &&*/
|
if (clip == CLIP_VISIBLE || GdClipPoint(psd, x, y))
|
if (clip == CLIP_VISIBLE || GdClipPoint(psd, x, y))
|
psd->DrawPixel(psd, x, y, pixel);
|
psd->DrawPixel(psd, x, y, pixel);
|
#if 0
|
#if 0
|
/* fix: use clipmaxx to clip quicker*/
|
/* fix: use clipmaxx to clip quicker*/
|
else if(clip != CLIP_VISIBLE && !clipresult && x > clipmaxx) {
|
else if(clip != CLIP_VISIBLE && !clipresult && x > clipmaxx) {
|
x = maxx;
|
x = maxx;
|
}
|
}
|
#endif
|
#endif
|
next:
|
next:
|
if(x++ == maxx) {
|
if(x++ == maxx) {
|
x = minx;
|
x = minx;
|
y += yoff;
|
y += yoff;
|
height--;
|
height--;
|
bitcount = 0;
|
bitcount = 0;
|
imagebits += extra;
|
imagebits += extra;
|
}
|
}
|
}
|
}
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/*
|
/*
|
* Read a rectangular area of the screen.
|
* Read a rectangular area of the screen.
|
* The color table is indexed row by row.
|
* The color table is indexed row by row.
|
*/
|
*/
|
void
|
void
|
GdReadArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
GdReadArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
MWPIXELVAL *pixels)
|
MWPIXELVAL *pixels)
|
{
|
{
|
MWCOORD row;
|
MWCOORD row;
|
MWCOORD col;
|
MWCOORD col;
|
|
|
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
return;
|
return;
|
|
|
GdCheckCursor(psd, x, y, x+width-1, y+height-1);
|
GdCheckCursor(psd, x, y, x+width-1, y+height-1);
|
for (row = y; row < height+y; row++)
|
for (row = y; row < height+y; row++)
|
for (col = x; col < width+x; col++)
|
for (col = x; col < width+x; col++)
|
if (row < 0 || row >= psd->yvirtres ||
|
if (row < 0 || row >= psd->yvirtres ||
|
col < 0 || col >= psd->xvirtres)
|
col < 0 || col >= psd->xvirtres)
|
*pixels++ = 0;
|
*pixels++ = 0;
|
else *pixels++ = psd->ReadPixel(psd, col, row);
|
else *pixels++ = psd->ReadPixel(psd, col, row);
|
|
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
/* Draw a rectangle of color values, clipping if necessary.
|
/* Draw a rectangle of color values, clipping if necessary.
|
* If a color matches the background color,
|
* If a color matches the background color,
|
* then that pixel is only drawn if the gr_usebg flag is set.
|
* then that pixel is only drawn if the gr_usebg flag is set.
|
*
|
*
|
* The pixels are packed according to pixtype:
|
* The pixels are packed according to pixtype:
|
*
|
*
|
* pixtype array of
|
* pixtype array of
|
* MWPF_RGB MWCOLORVAL (unsigned long)
|
* MWPF_RGB MWCOLORVAL (unsigned long)
|
* MWPF_PIXELVAL MWPIXELVAL (compile-time dependent)
|
* MWPF_PIXELVAL MWPIXELVAL (compile-time dependent)
|
* MWPF_PALETTE unsigned char
|
* MWPF_PALETTE unsigned char
|
* MWPF_TRUECOLOR0888 unsigned long
|
* MWPF_TRUECOLOR0888 unsigned long
|
* MWPF_TRUECOLOR888 packed struct {char r,char g,char b} (24 bits)
|
* MWPF_TRUECOLOR888 packed struct {char r,char g,char b} (24 bits)
|
* MWPF_TRUECOLOR565 unsigned short
|
* MWPF_TRUECOLOR565 unsigned short
|
* MWPF_TRUECOLOR555 unsigned short
|
* MWPF_TRUECOLOR555 unsigned short
|
* MWPF_TRUECOLOR332 unsigned char
|
* MWPF_TRUECOLOR332 unsigned char
|
*
|
*
|
* NOTE: Currently, no translation is performed if the pixtype
|
* NOTE: Currently, no translation is performed if the pixtype
|
* is not MWPF_RGB. Pixtype is only then used to determine the
|
* is not MWPF_RGB. Pixtype is only then used to determine the
|
* packed size of the pixel data, and is then stored unmodified
|
* packed size of the pixel data, and is then stored unmodified
|
* in a MWPIXELVAL and passed to the screen driver. Virtually,
|
* in a MWPIXELVAL and passed to the screen driver. Virtually,
|
* this means there's only three reasonable options for client
|
* this means there's only three reasonable options for client
|
* programs: (1) pass all data as RGB MWCOLORVALs, (2) pass
|
* programs: (1) pass all data as RGB MWCOLORVALs, (2) pass
|
* data as unpacked 32-bit MWPIXELVALs in the format the current
|
* data as unpacked 32-bit MWPIXELVALs in the format the current
|
* screen driver is running, or (3) pass data as packed values
|
* screen driver is running, or (3) pass data as packed values
|
* in the format the screen driver is running. Options 2 and 3
|
* in the format the screen driver is running. Options 2 and 3
|
* are identical except for the packing structure.
|
* are identical except for the packing structure.
|
*/
|
*/
|
void
|
void
|
GdArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height, void *pixels,
|
GdArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height, void *pixels,
|
int pixtype)
|
int pixtype)
|
{
|
{
|
unsigned char *PIXELS = pixels; /* for ANSI compilers, can't use void*/
|
unsigned char *PIXELS = pixels; /* for ANSI compilers, can't use void*/
|
long cellstodo; /* remaining number of cells */
|
long cellstodo; /* remaining number of cells */
|
long count; /* number of cells of same color */
|
long count; /* number of cells of same color */
|
long cc; /* current cell count */
|
long cc; /* current cell count */
|
long rows; /* number of complete rows */
|
long rows; /* number of complete rows */
|
MWCOORD minx; /* minimum x value */
|
MWCOORD minx; /* minimum x value */
|
MWCOORD maxx; /* maximum x value */
|
MWCOORD maxx; /* maximum x value */
|
MWPIXELVAL savecolor; /* saved foreground color */
|
MWPIXELVAL savecolor; /* saved foreground color */
|
MWBOOL dodraw; /* TRUE if draw these points */
|
MWBOOL dodraw; /* TRUE if draw these points */
|
MWCOLORVAL rgbcolor = 0L;
|
MWCOLORVAL rgbcolor = 0L;
|
int pixsize;
|
int pixsize;
|
unsigned char r, g, b;
|
unsigned char r, g, b;
|
|
|
minx = x;
|
minx = x;
|
maxx = x + width - 1;
|
maxx = x + width - 1;
|
|
|
/* Set up area clipping, and just return if nothing is visible */
|
/* Set up area clipping, and just return if nothing is visible */
|
if ( GdClipArea(psd, minx, y, maxx, y + height - 1) == CLIP_INVISIBLE )
|
if ( GdClipArea(psd, minx, y, maxx, y + height - 1) == CLIP_INVISIBLE )
|
return;
|
return;
|
|
|
/* psd->DrawArea driver call temp removed, doesn't work with new blit routines*/
|
/* psd->DrawArea driver call temp removed, doesn't work with new blit routines*/
|
#if 0000
|
#if 0000
|
{
|
{
|
driver_gc_t hwgc;
|
driver_gc_t hwgc;
|
int px1, px2, py1, py2, pw, ph, rx1, rx2, ry1, ry2;
|
int px1, px2, py1, py2, pw, ph, rx1, rx2, ry1, ry2;
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
MWRECT *prc;
|
MWRECT *prc;
|
extern MWCLIPREGION *clipregion;
|
extern MWCLIPREGION *clipregion;
|
#else
|
#else
|
MWCLIPRECT *prc;
|
MWCLIPRECT *prc;
|
extern MWCLIPRECT cliprects[];
|
extern MWCLIPRECT cliprects[];
|
extern int clipcount;
|
extern int clipcount;
|
#endif
|
#endif
|
|
|
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
|
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
|
/* can't use drawarea driver in 16 bpp mode yet with font routines*/
|
/* can't use drawarea driver in 16 bpp mode yet with font routines*/
|
goto fallback;
|
goto fallback;
|
#endif
|
#endif
|
if ( !(psd->flags & PSF_HAVEOP_COPY) )
|
if ( !(psd->flags & PSF_HAVEOP_COPY) )
|
goto fallback;
|
goto fallback;
|
|
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
prc = clipregion->rects;
|
prc = clipregion->rects;
|
count = clipregion->numRects;
|
count = clipregion->numRects;
|
#else
|
#else
|
prc = cliprects;
|
prc = cliprects;
|
count = clipcount;
|
count = clipcount;
|
#endif
|
#endif
|
|
|
hwgc.pixels = PIXELS;
|
hwgc.pixels = PIXELS;
|
hwgc.src_linelen = width;
|
hwgc.src_linelen = width;
|
hwgc.gr_usebg = gr_usebg;
|
hwgc.gr_usebg = gr_usebg;
|
hwgc.bg_color = gr_background;
|
hwgc.bg_color = gr_background;
|
|
|
while ( count-- > 0 ) {
|
while ( count-- > 0 ) {
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
rx1 = prc->left;
|
rx1 = prc->left;
|
ry1 = prc->top;
|
ry1 = prc->top;
|
rx2 = prc->right;
|
rx2 = prc->right;
|
ry2 = prc->bottom;
|
ry2 = prc->bottom;
|
#else
|
#else
|
/* New clip-code by Morten */
|
/* New clip-code by Morten */
|
rx1 = prc->x;
|
rx1 = prc->x;
|
ry1 = prc->y;
|
ry1 = prc->y;
|
rx2 = prc->x + prc->width;
|
rx2 = prc->x + prc->width;
|
ry2 = prc->y + prc->height;
|
ry2 = prc->y + prc->height;
|
#endif
|
#endif
|
|
|
/* Check if this rect intersects with the one we draw */
|
/* Check if this rect intersects with the one we draw */
|
px1 = x;
|
px1 = x;
|
py1 = y;
|
py1 = y;
|
px2 = x + width;
|
px2 = x + width;
|
py2 = y + height;
|
py2 = y + height;
|
if ( px1 < rx1 ) px1 = rx1;
|
if ( px1 < rx1 ) px1 = rx1;
|
if ( py1 < ry1 ) py1 = ry1;
|
if ( py1 < ry1 ) py1 = ry1;
|
if ( px2 > rx2 ) px2 = rx2;
|
if ( px2 > rx2 ) px2 = rx2;
|
if ( py2 > ry2 ) py2 = ry2;
|
if ( py2 > ry2 ) py2 = ry2;
|
|
|
pw = px2 - px1;
|
pw = px2 - px1;
|
ph = py2 - py1;
|
ph = py2 - py1;
|
|
|
if ( pw > 0 && ph > 0 ) {
|
if ( pw > 0 && ph > 0 ) {
|
hwgc.dstx = px1;
|
hwgc.dstx = px1;
|
hwgc.dsty = py1;
|
hwgc.dsty = py1;
|
hwgc.dstw = pw;
|
hwgc.dstw = pw;
|
hwgc.dsth = ph;
|
hwgc.dsth = ph;
|
hwgc.srcx = px1 - x;
|
hwgc.srcx = px1 - x;
|
hwgc.srcy = py1 - y;
|
hwgc.srcy = py1 - y;
|
GdCheckCursor(psd,px1,py1,px1+pw-1,py1+ph-1);
|
GdCheckCursor(psd,px1,py1,px1+pw-1,py1+ph-1);
|
psd->DrawArea(psd,&hwgc,PSDOP_COPY);
|
psd->DrawArea(psd,&hwgc,PSDOP_COPY);
|
}
|
}
|
prc++;
|
prc++;
|
}
|
}
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
return;
|
return;
|
fallback:
|
fallback:
|
}
|
}
|
#endif /* if 0000 temp removed*/
|
#endif /* if 0000 temp removed*/
|
|
|
/* Calculate size of packed pixels*/
|
/* Calculate size of packed pixels*/
|
switch(pixtype) {
|
switch(pixtype) {
|
case MWPF_RGB:
|
case MWPF_RGB:
|
pixsize = sizeof(MWCOLORVAL);
|
pixsize = sizeof(MWCOLORVAL);
|
break;
|
break;
|
case MWPF_PIXELVAL:
|
case MWPF_PIXELVAL:
|
pixsize = sizeof(MWPIXELVAL);
|
pixsize = sizeof(MWPIXELVAL);
|
break;
|
break;
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
pixsize = sizeof(unsigned char);
|
pixsize = sizeof(unsigned char);
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
pixsize = sizeof(unsigned long);
|
pixsize = sizeof(unsigned long);
|
break;
|
break;
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
pixsize = 3;
|
pixsize = 3;
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
pixsize = sizeof(unsigned short);
|
pixsize = sizeof(unsigned short);
|
break;
|
break;
|
default:
|
default:
|
return;
|
return;
|
}
|
}
|
|
|
savecolor = gr_foreground;
|
savecolor = gr_foreground;
|
cellstodo = (long)width * height;
|
cellstodo = (long)width * height;
|
while (cellstodo > 0) {
|
while (cellstodo > 0) {
|
/* read the pixel value from the pixtype*/
|
/* read the pixel value from the pixtype*/
|
switch(pixtype) {
|
switch(pixtype) {
|
case MWPF_RGB:
|
case MWPF_RGB:
|
rgbcolor = *(MWCOLORVAL *)PIXELS;
|
rgbcolor = *(MWCOLORVAL *)PIXELS;
|
PIXELS += sizeof(MWCOLORVAL);
|
PIXELS += sizeof(MWCOLORVAL);
|
gr_foreground = GdFindColor(rgbcolor);
|
gr_foreground = GdFindColor(rgbcolor);
|
break;
|
break;
|
case MWPF_PIXELVAL:
|
case MWPF_PIXELVAL:
|
gr_foreground = *(MWPIXELVAL *)PIXELS;
|
gr_foreground = *(MWPIXELVAL *)PIXELS;
|
PIXELS += sizeof(MWPIXELVAL);
|
PIXELS += sizeof(MWPIXELVAL);
|
break;
|
break;
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
gr_foreground = *PIXELS++;
|
gr_foreground = *PIXELS++;
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
gr_foreground = *(unsigned long *)PIXELS;
|
gr_foreground = *(unsigned long *)PIXELS;
|
PIXELS += sizeof(unsigned long);
|
PIXELS += sizeof(unsigned long);
|
break;
|
break;
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
r = *PIXELS++;
|
r = *PIXELS++;
|
g = *PIXELS++;
|
g = *PIXELS++;
|
b = *PIXELS++;
|
b = *PIXELS++;
|
gr_foreground = (MWPIXELVAL)MWRGB(r, g, b);
|
gr_foreground = (MWPIXELVAL)MWRGB(r, g, b);
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
gr_foreground = *(unsigned short *)PIXELS;
|
gr_foreground = *(unsigned short *)PIXELS;
|
PIXELS += sizeof(unsigned short);
|
PIXELS += sizeof(unsigned short);
|
break;
|
break;
|
}
|
}
|
dodraw = (gr_usebg || (gr_foreground != gr_background));
|
dodraw = (gr_usebg || (gr_foreground != gr_background));
|
count = 1;
|
count = 1;
|
--cellstodo;
|
--cellstodo;
|
|
|
/* See how many of the adjacent remaining points have the
|
/* See how many of the adjacent remaining points have the
|
* same color as the next point.
|
* same color as the next point.
|
*
|
*
|
* NOTE: Yes, with the addition of the pixel unpacking,
|
* NOTE: Yes, with the addition of the pixel unpacking,
|
* it's almost slower to look ahead than to just draw
|
* it's almost slower to look ahead than to just draw
|
* the pixel... FIXME
|
* the pixel... FIXME
|
*/
|
*/
|
while (cellstodo > 0) {
|
while (cellstodo > 0) {
|
switch(pixtype) {
|
switch(pixtype) {
|
case MWPF_RGB:
|
case MWPF_RGB:
|
if(rgbcolor != *(MWCOLORVAL *)PIXELS)
|
if(rgbcolor != *(MWCOLORVAL *)PIXELS)
|
goto breakwhile;
|
goto breakwhile;
|
PIXELS += sizeof(MWCOLORVAL);
|
PIXELS += sizeof(MWCOLORVAL);
|
break;
|
break;
|
case MWPF_PIXELVAL:
|
case MWPF_PIXELVAL:
|
if(gr_foreground != *(MWPIXELVAL *)PIXELS)
|
if(gr_foreground != *(MWPIXELVAL *)PIXELS)
|
goto breakwhile;
|
goto breakwhile;
|
PIXELS += sizeof(MWPIXELVAL);
|
PIXELS += sizeof(MWPIXELVAL);
|
break;
|
break;
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
if(gr_foreground != *(unsigned char *)PIXELS)
|
if(gr_foreground != *(unsigned char *)PIXELS)
|
goto breakwhile;
|
goto breakwhile;
|
++PIXELS;
|
++PIXELS;
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
if(gr_foreground != *(unsigned long *)PIXELS)
|
if(gr_foreground != *(unsigned long *)PIXELS)
|
goto breakwhile;
|
goto breakwhile;
|
PIXELS += sizeof(unsigned long);
|
PIXELS += sizeof(unsigned long);
|
break;
|
break;
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
r = *(unsigned char *)PIXELS;
|
r = *(unsigned char *)PIXELS;
|
g = *(unsigned char *)(PIXELS + 1);
|
g = *(unsigned char *)(PIXELS + 1);
|
b = *(unsigned char *)(PIXELS + 2);
|
b = *(unsigned char *)(PIXELS + 2);
|
if(gr_foreground != (MWPIXELVAL)MWRGB(r, g, b))
|
if(gr_foreground != (MWPIXELVAL)MWRGB(r, g, b))
|
goto breakwhile;
|
goto breakwhile;
|
PIXELS += 3;
|
PIXELS += 3;
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
if(gr_foreground != *(unsigned short *)PIXELS)
|
if(gr_foreground != *(unsigned short *)PIXELS)
|
goto breakwhile;
|
goto breakwhile;
|
PIXELS += sizeof(unsigned short);
|
PIXELS += sizeof(unsigned short);
|
break;
|
break;
|
}
|
}
|
++count;
|
++count;
|
--cellstodo;
|
--cellstodo;
|
}
|
}
|
breakwhile:
|
breakwhile:
|
|
|
/* If there is only one point with this color, then draw it
|
/* If there is only one point with this color, then draw it
|
* by itself.
|
* by itself.
|
*/
|
*/
|
if (count == 1) {
|
if (count == 1) {
|
if (dodraw)
|
if (dodraw)
|
drawpoint(psd, x, y);
|
drawpoint(psd, x, y);
|
if (++x > maxx) {
|
if (++x > maxx) {
|
x = minx;
|
x = minx;
|
y++;
|
y++;
|
}
|
}
|
continue;
|
continue;
|
}
|
}
|
|
|
/* There are multiple points with the same color. If we are
|
/* There are multiple points with the same color. If we are
|
* not at the start of a row of the rectangle, then draw this
|
* not at the start of a row of the rectangle, then draw this
|
* first row specially.
|
* first row specially.
|
*/
|
*/
|
if (x != minx) {
|
if (x != minx) {
|
cc = count;
|
cc = count;
|
if (x + cc - 1 > maxx)
|
if (x + cc - 1 > maxx)
|
cc = maxx - x + 1;
|
cc = maxx - x + 1;
|
if (dodraw)
|
if (dodraw)
|
drawrow(psd, x, x + cc - 1, y);
|
drawrow(psd, x, x + cc - 1, y);
|
count -= cc;
|
count -= cc;
|
x += cc;
|
x += cc;
|
if (x > maxx) {
|
if (x > maxx) {
|
x = minx;
|
x = minx;
|
y++;
|
y++;
|
}
|
}
|
}
|
}
|
|
|
/* Now the x value is at the beginning of a row if there are
|
/* Now the x value is at the beginning of a row if there are
|
* any points left to be drawn. Draw all the complete rows
|
* any points left to be drawn. Draw all the complete rows
|
* with one call.
|
* with one call.
|
*/
|
*/
|
rows = count / width;
|
rows = count / width;
|
if (rows > 0) {
|
if (rows > 0) {
|
if (dodraw) {
|
if (dodraw) {
|
/* note: change to fillrect, (parm types changed)*/
|
/* note: change to fillrect, (parm types changed)*/
|
/*GdFillRect(psd, x, y, maxx, y + rows - 1);*/
|
/*GdFillRect(psd, x, y, maxx, y + rows - 1);*/
|
GdFillRect(psd, x, y, maxx - x + 1, rows);
|
GdFillRect(psd, x, y, maxx - x + 1, rows);
|
}
|
}
|
count %= width;
|
count %= width;
|
y += rows;
|
y += rows;
|
}
|
}
|
|
|
/* If there is a final partial row of pixels left to be
|
/* If there is a final partial row of pixels left to be
|
* drawn, then do that.
|
* drawn, then do that.
|
*/
|
*/
|
if (count > 0) {
|
if (count > 0) {
|
if (dodraw)
|
if (dodraw)
|
drawrow(psd, x, x + count - 1, y);
|
drawrow(psd, x, x + count - 1, y);
|
x += count;
|
x += count;
|
}
|
}
|
}
|
}
|
gr_foreground = savecolor;
|
gr_foreground = savecolor;
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
|
|
#if NOTYET
|
#if NOTYET
|
/* Copy a rectangular area from one screen area to another.
|
/* Copy a rectangular area from one screen area to another.
|
* This bypasses clipping.
|
* This bypasses clipping.
|
*/
|
*/
|
void
|
void
|
GdCopyArea(PSD psd, MWCOORD srcx, MWCOORD srcy, MWCOORD width, MWCOORD height,
|
GdCopyArea(PSD psd, MWCOORD srcx, MWCOORD srcy, MWCOORD width, MWCOORD height,
|
MWCOORD destx, MWCOORD desty)
|
MWCOORD destx, MWCOORD desty)
|
{
|
{
|
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
return;
|
return;
|
|
|
if (srcx == destx && srcy == desty)
|
if (srcx == destx && srcy == desty)
|
return;
|
return;
|
GdCheckCursor(psd, srcx, srcy, srcx + width - 1, srcy + height - 1);
|
GdCheckCursor(psd, srcx, srcy, srcx + width - 1, srcy + height - 1);
|
GdCheckCursor(psd, destx, desty, destx + width - 1, desty + height - 1);
|
GdCheckCursor(psd, destx, desty, destx + width - 1, desty + height - 1);
|
psd->CopyArea(psd, srcx, srcy, width, height, destx, desty);
|
psd->CopyArea(psd, srcx, srcy, width, height, destx, desty);
|
GdFixCursor(psd);
|
GdFixCursor(psd);
|
}
|
}
|
#endif
|
#endif
|
|
|
/* Copy source rectangle of pixels to destination rectangle quickly*/
|
/* Copy source rectangle of pixels to destination rectangle quickly*/
|
void
|
void
|
GdBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD width, MWCOORD height,
|
GdBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD width, MWCOORD height,
|
PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long rop)
|
PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long rop)
|
{
|
{
|
int rx1, rx2, ry1, ry2;
|
int rx1, rx2, ry1, ry2;
|
int px1, px2, py1, py2;
|
int px1, px2, py1, py2;
|
int pw, ph;
|
int pw, ph;
|
int count;
|
int count;
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
MWRECT * prc;
|
MWRECT * prc;
|
extern MWCLIPREGION *clipregion;
|
extern MWCLIPREGION *clipregion;
|
#else
|
#else
|
MWCLIPRECT * prc;
|
MWCLIPRECT * prc;
|
extern MWCLIPRECT cliprects[];
|
extern MWCLIPRECT cliprects[];
|
extern int clipcount;
|
extern int clipcount;
|
#endif
|
#endif
|
|
|
/*FIXME: compare bpp's and convert if necessary*/
|
/*FIXME: compare bpp's and convert if necessary*/
|
assert(dstpsd->planes == srcpsd->planes);
|
assert(dstpsd->planes == srcpsd->planes);
|
assert(dstpsd->bpp == srcpsd->bpp);
|
assert(dstpsd->bpp == srcpsd->bpp);
|
|
|
/* temporary assert() until rotation blits completed*/
|
/* temporary assert() until rotation blits completed*/
|
assert(dstpsd->portrait == srcpsd->portrait);
|
assert(dstpsd->portrait == srcpsd->portrait);
|
|
|
/* clip blit rectangle to source screen/bitmap size*/
|
/* clip blit rectangle to source screen/bitmap size*/
|
/* we must do this because there isn't any source clipping setup*/
|
/* we must do this because there isn't any source clipping setup*/
|
if(srcx < 0) {
|
if(srcx < 0) {
|
width += srcx;
|
width += srcx;
|
dstx -= srcx;
|
dstx -= srcx;
|
srcx = 0;
|
srcx = 0;
|
}
|
}
|
if(srcy < 0) {
|
if(srcy < 0) {
|
height += srcy;
|
height += srcy;
|
dsty -= srcy;
|
dsty -= srcy;
|
srcy = 0;
|
srcy = 0;
|
}
|
}
|
if(srcx+width > srcpsd->xvirtres)
|
if(srcx+width > srcpsd->xvirtres)
|
width = srcpsd->xvirtres - srcx;
|
width = srcpsd->xvirtres - srcx;
|
if(srcy+height > srcpsd->yvirtres)
|
if(srcy+height > srcpsd->yvirtres)
|
height = srcpsd->yvirtres - srcy;
|
height = srcpsd->yvirtres - srcy;
|
|
|
switch(GdClipArea(dstpsd, dstx, dsty, dstx+width-1, dsty+height-1)) {
|
switch(GdClipArea(dstpsd, dstx, dsty, dstx+width-1, dsty+height-1)) {
|
case CLIP_VISIBLE:
|
case CLIP_VISIBLE:
|
/* check cursor in src region*/
|
/* check cursor in src region*/
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+width-1, srcy+height-1);
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+width-1, srcy+height-1);
|
dstpsd->Blit(dstpsd, dstx, dsty, width, height,
|
dstpsd->Blit(dstpsd, dstx, dsty, width, height,
|
srcpsd, srcx, srcy, rop);
|
srcpsd, srcx, srcy, rop);
|
GdFixCursor(dstpsd);
|
GdFixCursor(dstpsd);
|
return;
|
return;
|
|
|
case CLIP_INVISIBLE:
|
case CLIP_INVISIBLE:
|
return;
|
return;
|
}
|
}
|
|
|
/* Partly clipped, we'll blit using destination clip
|
/* Partly clipped, we'll blit using destination clip
|
* rectangles, and offset the blit accordingly.
|
* rectangles, and offset the blit accordingly.
|
* Since the destination is already clipped, we
|
* Since the destination is already clipped, we
|
* only need to clip the source here.
|
* only need to clip the source here.
|
*/
|
*/
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
prc = clipregion->rects;
|
prc = clipregion->rects;
|
count = clipregion->numRects;
|
count = clipregion->numRects;
|
#else
|
#else
|
prc = cliprects;
|
prc = cliprects;
|
count = clipcount;
|
count = clipcount;
|
#endif
|
#endif
|
while(--count >= 0) {
|
while(--count >= 0) {
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
rx1 = prc->left;
|
rx1 = prc->left;
|
ry1 = prc->top;
|
ry1 = prc->top;
|
rx2 = prc->right;
|
rx2 = prc->right;
|
ry2 = prc->bottom;
|
ry2 = prc->bottom;
|
#else
|
#else
|
rx1 = prc->x;
|
rx1 = prc->x;
|
ry1 = prc->y;
|
ry1 = prc->y;
|
rx2 = prc->x + prc->width;
|
rx2 = prc->x + prc->width;
|
ry2 = prc->y + prc->height;
|
ry2 = prc->y + prc->height;
|
#endif
|
#endif
|
/* Check: does this rect intersect the one we want to draw? */
|
/* Check: does this rect intersect the one we want to draw? */
|
px1 = dstx;
|
px1 = dstx;
|
py1 = dsty;
|
py1 = dsty;
|
px2 = dstx + width;
|
px2 = dstx + width;
|
py2 = dsty + height;
|
py2 = dsty + height;
|
if (px1 < rx1) px1 = rx1;
|
if (px1 < rx1) px1 = rx1;
|
if (py1 < ry1) py1 = ry1;
|
if (py1 < ry1) py1 = ry1;
|
if (px2 > rx2) px2 = rx2;
|
if (px2 > rx2) px2 = rx2;
|
if (py2 > ry2) py2 = ry2;
|
if (py2 > ry2) py2 = ry2;
|
|
|
pw = px2 - px1;
|
pw = px2 - px1;
|
ph = py2 - py1;
|
ph = py2 - py1;
|
if(pw > 0 && ph > 0) {
|
if(pw > 0 && ph > 0) {
|
/* check cursor in dest and src regions*/
|
/* check cursor in dest and src regions*/
|
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
|
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
|
GdCheckCursor(dstpsd, srcx, srcy,
|
GdCheckCursor(dstpsd, srcx, srcy,
|
srcx+width, srcy+height);
|
srcx+width, srcy+height);
|
dstpsd->Blit(dstpsd, px1, py1, pw, ph, srcpsd,
|
dstpsd->Blit(dstpsd, px1, py1, pw, ph, srcpsd,
|
srcx + (px1-dstx), srcy + (py1-dsty), rop);
|
srcx + (px1-dstx), srcy + (py1-dsty), rop);
|
}
|
}
|
++prc;
|
++prc;
|
}
|
}
|
GdFixCursor(dstpsd);
|
GdFixCursor(dstpsd);
|
}
|
}
|
|
|
/* experimental globals for ratio bug when src != 0*/
|
/* experimental globals for ratio bug when src != 0*/
|
int g_row_inc, g_col_inc;
|
int g_row_inc, g_col_inc;
|
/* Stretch source rectangle of pixels to destination rectangle quickly*/
|
/* Stretch source rectangle of pixels to destination rectangle quickly*/
|
void
|
void
|
GdStretchBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
|
GdStretchBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
|
MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
|
MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
|
MWCOORD srch, long rop)
|
MWCOORD srch, long rop)
|
{
|
{
|
int count;
|
int count;
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
MWRECT * prc;
|
MWRECT * prc;
|
extern MWCLIPREGION *clipregion;
|
extern MWCLIPREGION *clipregion;
|
#else
|
#else
|
MWCLIPRECT * prc;
|
MWCLIPRECT * prc;
|
extern MWCLIPRECT cliprects[];
|
extern MWCLIPRECT cliprects[];
|
extern int clipcount;
|
extern int clipcount;
|
#endif
|
#endif
|
|
|
g_row_inc = g_col_inc = 0;
|
g_row_inc = g_col_inc = 0;
|
|
|
/* check for driver stretch blit implementation*/
|
/* check for driver stretch blit implementation*/
|
if (!dstpsd->StretchBlit)
|
if (!dstpsd->StretchBlit)
|
return;
|
return;
|
|
|
/*FIXME: compare bpp's and convert if necessary*/
|
/*FIXME: compare bpp's and convert if necessary*/
|
assert(dstpsd->planes == srcpsd->planes);
|
assert(dstpsd->planes == srcpsd->planes);
|
assert(dstpsd->bpp == srcpsd->bpp);
|
assert(dstpsd->bpp == srcpsd->bpp);
|
|
|
/* clip blit rectangle to source screen/bitmap size*/
|
/* clip blit rectangle to source screen/bitmap size*/
|
/* we must do this because there isn't any source clipping setup*/
|
/* we must do this because there isn't any source clipping setup*/
|
if(srcx < 0) {
|
if(srcx < 0) {
|
srcw += srcx;
|
srcw += srcx;
|
/*dstx -= srcx;*/
|
/*dstx -= srcx;*/
|
srcx = 0;
|
srcx = 0;
|
}
|
}
|
if(srcy < 0) {
|
if(srcy < 0) {
|
srch += srcy;
|
srch += srcy;
|
/*dsty -= srcy;*/
|
/*dsty -= srcy;*/
|
srcy = 0;
|
srcy = 0;
|
}
|
}
|
if(srcx+srcw > srcpsd->xvirtres)
|
if(srcx+srcw > srcpsd->xvirtres)
|
srcw = srcpsd->xvirtres - srcx;
|
srcw = srcpsd->xvirtres - srcx;
|
if(srcy+srch > srcpsd->yvirtres)
|
if(srcy+srch > srcpsd->yvirtres)
|
srch = srcpsd->yvirtres - srcy;
|
srch = srcpsd->yvirtres - srcy;
|
|
|
/* temp dest clipping for partially visible case*/
|
/* temp dest clipping for partially visible case*/
|
if(dstx+dstw > dstpsd->xvirtres)
|
if(dstx+dstw > dstpsd->xvirtres)
|
dstw = dstpsd->xvirtres - dstx;
|
dstw = dstpsd->xvirtres - dstx;
|
if(dsty+dsth > dstpsd->yvirtres)
|
if(dsty+dsth > dstpsd->yvirtres)
|
dsth = dstpsd->yvirtres - dsty;
|
dsth = dstpsd->yvirtres - dsty;
|
|
|
switch(GdClipArea(dstpsd, dstx, dsty, dstx+dstw-1, dsty+dsth-1)) {
|
switch(GdClipArea(dstpsd, dstx, dsty, dstx+dstw-1, dsty+dsth-1)) {
|
case CLIP_VISIBLE:
|
case CLIP_VISIBLE:
|
/* check cursor in src region*/
|
/* check cursor in src region*/
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw-1, srcy+srch-1);
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw-1, srcy+srch-1);
|
dstpsd->StretchBlit(dstpsd, dstx, dsty, dstw, dsth,
|
dstpsd->StretchBlit(dstpsd, dstx, dsty, dstw, dsth,
|
srcpsd, srcx, srcy, srcw, srch, rop);
|
srcpsd, srcx, srcy, srcw, srch, rop);
|
GdFixCursor(dstpsd);
|
GdFixCursor(dstpsd);
|
return;
|
return;
|
|
|
case CLIP_INVISIBLE:
|
case CLIP_INVISIBLE:
|
return;
|
return;
|
}
|
}
|
|
|
/* Partly clipped, we'll blit using destination clip
|
/* Partly clipped, we'll blit using destination clip
|
* rectangles, and offset the blit accordingly.
|
* rectangles, and offset the blit accordingly.
|
* Since the destination is already clipped, we
|
* Since the destination is already clipped, we
|
* only need to clip the source here.
|
* only need to clip the source here.
|
*/
|
*/
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
prc = clipregion->rects;
|
prc = clipregion->rects;
|
count = clipregion->numRects;
|
count = clipregion->numRects;
|
#else
|
#else
|
prc = cliprects;
|
prc = cliprects;
|
count = clipcount;
|
count = clipcount;
|
#endif
|
#endif
|
while(--count >= 0) {
|
while(--count >= 0) {
|
int rx1, rx2, ry1, ry2;
|
int rx1, rx2, ry1, ry2;
|
int px1, px2, py1, py2;
|
int px1, px2, py1, py2;
|
int pw, ph;
|
int pw, ph;
|
int sx, sy, sw, sh;
|
int sx, sy, sw, sh;
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
rx1 = prc->left;
|
rx1 = prc->left;
|
ry1 = prc->top;
|
ry1 = prc->top;
|
rx2 = prc->right;
|
rx2 = prc->right;
|
ry2 = prc->bottom;
|
ry2 = prc->bottom;
|
#else
|
#else
|
rx1 = prc->x;
|
rx1 = prc->x;
|
ry1 = prc->y;
|
ry1 = prc->y;
|
rx2 = prc->x + prc->width;
|
rx2 = prc->x + prc->width;
|
ry2 = prc->y + prc->height;
|
ry2 = prc->y + prc->height;
|
#endif
|
#endif
|
/* Check: does this rect intersect the one we want to draw? */
|
/* Check: does this rect intersect the one we want to draw? */
|
px1 = dstx;
|
px1 = dstx;
|
py1 = dsty;
|
py1 = dsty;
|
px2 = dstx + dstw;
|
px2 = dstx + dstw;
|
py2 = dsty + dsth;
|
py2 = dsty + dsth;
|
if (px1 < rx1) px1 = rx1;
|
if (px1 < rx1) px1 = rx1;
|
if (py1 < ry1) py1 = ry1;
|
if (py1 < ry1) py1 = ry1;
|
if (px2 > rx2) px2 = rx2;
|
if (px2 > rx2) px2 = rx2;
|
if (py2 > ry2) py2 = ry2;
|
if (py2 > ry2) py2 = ry2;
|
|
|
pw = px2 - px1;
|
pw = px2 - px1;
|
ph = py2 - py1;
|
ph = py2 - py1;
|
if(pw > 0 && ph > 0) {
|
if(pw > 0 && ph > 0) {
|
/* calc proper src/dst offset for stretch rect*/
|
/* calc proper src/dst offset for stretch rect*/
|
g_row_inc = (srch << 16) / dsth;
|
g_row_inc = (srch << 16) / dsth;
|
g_col_inc = (srcw << 16) / dstw;
|
g_col_inc = (srcw << 16) / dstw;
|
sw = pw * srcw / dstw;
|
sw = pw * srcw / dstw;
|
sh = ph * srch / dsth;
|
sh = ph * srch / dsth;
|
|
|
if (sw > 0 && sh > 0) {
|
if (sw > 0 && sh > 0) {
|
sx = srcx + (px1-dstx) * srcw / dstw;
|
sx = srcx + (px1-dstx) * srcw / dstw;
|
sy = srcy + (py1-dsty) * srch / dsth;
|
sy = srcy + (py1-dsty) * srch / dsth;
|
/*printf("P %d,%d,%d,%d %d,%d\n", sx, sy, sw, sh, g_row_inc, g_col_inc);*/
|
/*printf("P %d,%d,%d,%d %d,%d\n", sx, sy, sw, sh, g_row_inc, g_col_inc);*/
|
|
|
/* check cursor in dest and src regions*/
|
/* check cursor in dest and src regions*/
|
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
|
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw, srcy+srch);
|
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw, srcy+srch);
|
dstpsd->StretchBlit(dstpsd, px1, py1, pw, ph, srcpsd,
|
dstpsd->StretchBlit(dstpsd, px1, py1, pw, ph, srcpsd,
|
sx, sy, sw, sh, rop);
|
sx, sy, sw, sh, rop);
|
}
|
}
|
}
|
}
|
++prc;
|
++prc;
|
}
|
}
|
GdFixCursor(dstpsd);
|
GdFixCursor(dstpsd);
|
}
|
}
|
|
|
/*
|
/*
|
* Calculate size and linelen of memory gc.
|
* Calculate size and linelen of memory gc.
|
* If bpp or planes is 0, use passed psd's bpp/planes.
|
* If bpp or planes is 0, use passed psd's bpp/planes.
|
* Note: linelen is calculated to be DWORD aligned for speed
|
* Note: linelen is calculated to be DWORD aligned for speed
|
* for bpp <= 8. Linelen is converted to bytelen for bpp > 8.
|
* for bpp <= 8. Linelen is converted to bytelen for bpp > 8.
|
*/
|
*/
|
int
|
int
|
GdCalcMemGCAlloc(PSD psd, unsigned int width, unsigned int height, int planes,
|
GdCalcMemGCAlloc(PSD psd, unsigned int width, unsigned int height, int planes,
|
int bpp, int *psize, int *plinelen)
|
int bpp, int *psize, int *plinelen)
|
{
|
{
|
int bytelen, linelen, tmp;
|
int bytelen, linelen, tmp;
|
|
|
if(!planes)
|
if(!planes)
|
planes = psd->planes;
|
planes = psd->planes;
|
if(!bpp)
|
if(!bpp)
|
bpp = psd->bpp;
|
bpp = psd->bpp;
|
/*
|
/*
|
* swap width and height in left/right portrait modes,
|
* swap width and height in left/right portrait modes,
|
* so imagesize is calculated properly
|
* so imagesize is calculated properly
|
*/
|
*/
|
if(psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT)) {
|
if(psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT)) {
|
tmp = width;
|
tmp = width;
|
width = height;
|
width = height;
|
height = tmp;
|
height = tmp;
|
}
|
}
|
|
|
/*
|
/*
|
* use bpp and planes to create size and linelen.
|
* use bpp and planes to create size and linelen.
|
* linelen is in bytes for bpp 1, 2, 4, 8, and pixels for bpp 16,24,32.
|
* linelen is in bytes for bpp 1, 2, 4, 8, and pixels for bpp 16,24,32.
|
*/
|
*/
|
if(planes == 1) {
|
if(planes == 1) {
|
switch(bpp) {
|
switch(bpp) {
|
case 1:
|
case 1:
|
linelen = (width+7)/8;
|
linelen = (width+7)/8;
|
bytelen = linelen = (linelen+3) & ~3;
|
bytelen = linelen = (linelen+3) & ~3;
|
break;
|
break;
|
case 2:
|
case 2:
|
linelen = (width+3)/4;
|
linelen = (width+3)/4;
|
bytelen = linelen = (linelen+3) & ~3;
|
bytelen = linelen = (linelen+3) & ~3;
|
break;
|
break;
|
case 4:
|
case 4:
|
linelen = (width+1)/2;
|
linelen = (width+1)/2;
|
bytelen = linelen = (linelen+3) & ~3;
|
bytelen = linelen = (linelen+3) & ~3;
|
break;
|
break;
|
case 8:
|
case 8:
|
bytelen = linelen = (width+3) & ~3;
|
bytelen = linelen = (width+3) & ~3;
|
break;
|
break;
|
case 16:
|
case 16:
|
linelen = width;
|
linelen = width;
|
bytelen = width * 2;
|
bytelen = width * 2;
|
break;
|
break;
|
case 24:
|
case 24:
|
linelen = width;
|
linelen = width;
|
bytelen = width * 3;
|
bytelen = width * 3;
|
break;
|
break;
|
case 32:
|
case 32:
|
linelen = width;
|
linelen = width;
|
bytelen = width * 4;
|
bytelen = width * 4;
|
break;
|
break;
|
default:
|
default:
|
return 0;
|
return 0;
|
}
|
}
|
} else if(planes == 4) {
|
} else if(planes == 4) {
|
/* FIXME assumes VGA 4 planes 4bpp*/
|
/* FIXME assumes VGA 4 planes 4bpp*/
|
/* we use 4bpp linear for memdc format*/
|
/* we use 4bpp linear for memdc format*/
|
linelen = (width+1)/2;
|
linelen = (width+1)/2;
|
linelen = (linelen+3) & ~3;
|
linelen = (linelen+3) & ~3;
|
bytelen = linelen;
|
bytelen = linelen;
|
} else {
|
} else {
|
*psize = *plinelen = 0;
|
*psize = *plinelen = 0;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
*plinelen = linelen;
|
*plinelen = linelen;
|
*psize = bytelen * height;
|
*psize = bytelen * height;
|
return 1;
|
return 1;
|
}
|
}
|
|
|
/* Translate a rectangle of color values
|
/* Translate a rectangle of color values
|
*
|
*
|
* The pixels are packed according to inpixtype/outpixtype:
|
* The pixels are packed according to inpixtype/outpixtype:
|
*
|
*
|
* pixtype array of
|
* pixtype array of
|
* MWPF_RGB MWCOLORVAL (unsigned long)
|
* MWPF_RGB MWCOLORVAL (unsigned long)
|
* MWPF_PIXELVAL MWPIXELVAL (compile-time dependent)
|
* MWPF_PIXELVAL MWPIXELVAL (compile-time dependent)
|
* MWPF_PALETTE unsigned char
|
* MWPF_PALETTE unsigned char
|
* MWPF_TRUECOLOR0888 unsigned long
|
* MWPF_TRUECOLOR0888 unsigned long
|
* MWPF_TRUECOLOR888 packed struct {char r,char g,char b} (24 bits)
|
* MWPF_TRUECOLOR888 packed struct {char r,char g,char b} (24 bits)
|
* MWPF_TRUECOLOR565 unsigned short
|
* MWPF_TRUECOLOR565 unsigned short
|
* MWPF_TRUECOLOR555 unsigned short
|
* MWPF_TRUECOLOR555 unsigned short
|
* MWPF_TRUECOLOR332 unsigned char
|
* MWPF_TRUECOLOR332 unsigned char
|
*/
|
*/
|
void
|
void
|
GdTranslateArea(MWCOORD width, MWCOORD height, void *in, int inpixtype,
|
GdTranslateArea(MWCOORD width, MWCOORD height, void *in, int inpixtype,
|
MWCOORD inpitch, void *out, int outpixtype, int outpitch)
|
MWCOORD inpitch, void *out, int outpixtype, int outpitch)
|
{
|
{
|
unsigned char * inbuf = in;
|
unsigned char * inbuf = in;
|
unsigned char * outbuf = out;
|
unsigned char * outbuf = out;
|
unsigned long pixelval;
|
unsigned long pixelval;
|
MWCOLORVAL colorval;
|
MWCOLORVAL colorval;
|
MWCOORD x, y;
|
MWCOORD x, y;
|
unsigned char r, g, b;
|
unsigned char r, g, b;
|
extern MWPALENTRY gr_palette[256];
|
extern MWPALENTRY gr_palette[256];
|
int gr_palsize = 256; /* FIXME*/
|
int gr_palsize = 256; /* FIXME*/
|
|
|
for(y=0; y<height; ++y) {
|
for(y=0; y<height; ++y) {
|
for(x=0; x<width; ++x) {
|
for(x=0; x<width; ++x) {
|
/* read pixel value and convert to BGR colorval (0x00BBGGRR)*/
|
/* read pixel value and convert to BGR colorval (0x00BBGGRR)*/
|
switch (inpixtype) {
|
switch (inpixtype) {
|
case MWPF_RGB:
|
case MWPF_RGB:
|
colorval = *(MWCOLORVAL *)inbuf;
|
colorval = *(MWCOLORVAL *)inbuf;
|
inbuf += sizeof(MWCOLORVAL);
|
inbuf += sizeof(MWCOLORVAL);
|
break;
|
break;
|
case MWPF_PIXELVAL:
|
case MWPF_PIXELVAL:
|
pixelval = *(MWPIXELVAL *)inbuf;
|
pixelval = *(MWPIXELVAL *)inbuf;
|
inbuf += sizeof(MWPIXELVAL);
|
inbuf += sizeof(MWPIXELVAL);
|
/* convert based on compile-time MWPIXEL_FORMAT*/
|
/* convert based on compile-time MWPIXEL_FORMAT*/
|
#if MWPIXEL_FORMAT == MWPF_PALETTE
|
#if MWPIXEL_FORMAT == MWPF_PALETTE
|
colorval = GETPALENTRY(gr_palette, pixelval);
|
colorval = GETPALENTRY(gr_palette, pixelval);
|
#else
|
#else
|
colorval = PIXELVALTOCOLORVAL(pixelval);
|
colorval = PIXELVALTOCOLORVAL(pixelval);
|
#endif
|
#endif
|
break;
|
break;
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
pixelval = *inbuf++;
|
pixelval = *inbuf++;
|
colorval = GETPALENTRY(gr_palette, pixelval);
|
colorval = GETPALENTRY(gr_palette, pixelval);
|
break;
|
break;
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
pixelval = *inbuf++;
|
pixelval = *inbuf++;
|
colorval = PIXEL332TOCOLORVAL(pixelval);
|
colorval = PIXEL332TOCOLORVAL(pixelval);
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
pixelval = *(unsigned long *)inbuf;
|
pixelval = *(unsigned long *)inbuf;
|
colorval = PIXEL888TOCOLORVAL(pixelval);
|
colorval = PIXEL888TOCOLORVAL(pixelval);
|
inbuf += sizeof(unsigned long);
|
inbuf += sizeof(unsigned long);
|
break;
|
break;
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
r = *inbuf++;
|
r = *inbuf++;
|
g = *inbuf++;
|
g = *inbuf++;
|
b = *inbuf++;
|
b = *inbuf++;
|
colorval = (MWPIXELVAL)MWRGB(r, g, b);
|
colorval = (MWPIXELVAL)MWRGB(r, g, b);
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
pixelval = *(unsigned short *)inbuf;
|
pixelval = *(unsigned short *)inbuf;
|
colorval = PIXEL565TOCOLORVAL(pixelval);
|
colorval = PIXEL565TOCOLORVAL(pixelval);
|
inbuf += sizeof(unsigned short);
|
inbuf += sizeof(unsigned short);
|
break;
|
break;
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
pixelval = *(unsigned short *)inbuf;
|
pixelval = *(unsigned short *)inbuf;
|
colorval = PIXEL555TOCOLORVAL(pixelval);
|
colorval = PIXEL555TOCOLORVAL(pixelval);
|
inbuf += sizeof(unsigned short);
|
inbuf += sizeof(unsigned short);
|
break;
|
break;
|
default:
|
default:
|
return;
|
return;
|
}
|
}
|
|
|
/* convert from BGR colorval to desired output pixel format*/
|
/* convert from BGR colorval to desired output pixel format*/
|
switch (outpixtype) {
|
switch (outpixtype) {
|
case MWPF_RGB:
|
case MWPF_RGB:
|
*(MWCOLORVAL *)outbuf = colorval;
|
*(MWCOLORVAL *)outbuf = colorval;
|
outbuf += sizeof(MWCOLORVAL);
|
outbuf += sizeof(MWCOLORVAL);
|
break;
|
break;
|
case MWPF_PIXELVAL:
|
case MWPF_PIXELVAL:
|
/* convert based on compile-time MWPIXEL_FORMAT*/
|
/* convert based on compile-time MWPIXEL_FORMAT*/
|
#if MWPIXEL_FORMAT == MWPF_PALETTE
|
#if MWPIXEL_FORMAT == MWPF_PALETTE
|
*(MWPIXELVAL *)outbuf = GdFindNearestColor(gr_palette,
|
*(MWPIXELVAL *)outbuf = GdFindNearestColor(gr_palette,
|
gr_palsize, colorval);
|
gr_palsize, colorval);
|
#else
|
#else
|
*(MWPIXELVAL *)outbuf = COLORVALTOPIXELVAL(colorval);
|
*(MWPIXELVAL *)outbuf = COLORVALTOPIXELVAL(colorval);
|
#endif
|
#endif
|
outbuf += sizeof(MWPIXELVAL);
|
outbuf += sizeof(MWPIXELVAL);
|
break;
|
break;
|
case MWPF_PALETTE:
|
case MWPF_PALETTE:
|
*outbuf++ = GdFindNearestColor(gr_palette, gr_palsize,
|
*outbuf++ = GdFindNearestColor(gr_palette, gr_palsize,
|
colorval);
|
colorval);
|
break;
|
break;
|
case MWPF_TRUECOLOR332:
|
case MWPF_TRUECOLOR332:
|
*outbuf++ = COLOR2PIXEL332(colorval);
|
*outbuf++ = COLOR2PIXEL332(colorval);
|
break;
|
break;
|
case MWPF_TRUECOLOR0888:
|
case MWPF_TRUECOLOR0888:
|
*(unsigned long *)outbuf = COLOR2PIXEL888(colorval);
|
*(unsigned long *)outbuf = COLOR2PIXEL888(colorval);
|
outbuf += sizeof(unsigned long);
|
outbuf += sizeof(unsigned long);
|
break;
|
break;
|
case MWPF_TRUECOLOR888:
|
case MWPF_TRUECOLOR888:
|
*outbuf++ = REDVALUE(colorval);
|
*outbuf++ = REDVALUE(colorval);
|
*outbuf++ = GREENVALUE(colorval);
|
*outbuf++ = GREENVALUE(colorval);
|
*outbuf++ = BLUEVALUE(colorval);
|
*outbuf++ = BLUEVALUE(colorval);
|
break;
|
break;
|
case MWPF_TRUECOLOR565:
|
case MWPF_TRUECOLOR565:
|
*(unsigned short *)outbuf = COLOR2PIXEL565(colorval);
|
*(unsigned short *)outbuf = COLOR2PIXEL565(colorval);
|
outbuf += sizeof(unsigned short);
|
outbuf += sizeof(unsigned short);
|
break;
|
break;
|
case MWPF_TRUECOLOR555:
|
case MWPF_TRUECOLOR555:
|
*(unsigned short *)outbuf = COLOR2PIXEL555(colorval);
|
*(unsigned short *)outbuf = COLOR2PIXEL555(colorval);
|
outbuf += sizeof(unsigned short);
|
outbuf += sizeof(unsigned short);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/* adjust line widths, if necessary*/
|
/* adjust line widths, if necessary*/
|
if(inpitch > width)
|
if(inpitch > width)
|
inbuf += inpitch - width;
|
inbuf += inpitch - width;
|
if(outpitch > width)
|
if(outpitch > width)
|
outbuf += outpitch - width;
|
outbuf += outpitch - width;
|
}
|
}
|
}
|
}
|
|
|