OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [engine/] [devdraw.c] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
/*
/*
 * 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;
        }
        }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.