Added StretchDIBits for the PostScript driver.

diff --git a/graphics/psdrv/bitmap.c b/graphics/psdrv/bitmap.c
index 6cf8e1f..450d72a 100644
--- a/graphics/psdrv/bitmap.c
+++ b/graphics/psdrv/bitmap.c
@@ -8,22 +8,209 @@
 #include "gdi.h"
 #include "psdrv.h"
 #include "debug.h"
+#include "bitmap.h"
+#include "winbase.h"
+
+
+/***************************************************************************
+ *                PSDRV_WriteImageHeader
+ *
+ * Helper for PSDRV_StretchDIBits
+ *
+ * BUGS
+ *  Uses level 2 PostScript
+ */
+
+static BOOL PSDRV_WriteImageHeader(DC *dc, const BITMAPINFO *info, INT xDst,
+				   INT yDst, INT widthDst, INT heightDst,
+				   INT widthSrc, INT heightSrc)
+{
+    COLORREF map[256];
+    int i;
+
+    switch(info->bmiHeader.biBitCount) {
+    case 8:
+        PSDRV_WriteIndexColorSpaceBegin(dc, 255);
+	for(i = 0; i < 256; i++) {
+	    map[i] =  info->bmiColors[i].rgbRed |
+	      info->bmiColors[i].rgbGreen << 8 |
+	      info->bmiColors[i].rgbBlue << 16;
+	}
+	PSDRV_WriteRGB(dc, map, 256);
+	PSDRV_WriteIndexColorSpaceEnd(dc);
+	break;
+
+    case 4:
+        PSDRV_WriteIndexColorSpaceBegin(dc, 15);
+	for(i = 0; i < 16; i++) {
+	    map[i] =  info->bmiColors[i].rgbRed |
+	      info->bmiColors[i].rgbGreen << 8 |
+	      info->bmiColors[i].rgbBlue << 16;
+	}
+	PSDRV_WriteRGB(dc, map, 16);
+	PSDRV_WriteIndexColorSpaceEnd(dc);
+	break;
+
+    case 1:
+        PSDRV_WriteIndexColorSpaceBegin(dc, 1);
+	for(i = 0; i < 2; i++) {
+	    map[i] =  info->bmiColors[i].rgbRed |
+	      info->bmiColors[i].rgbGreen << 8 |
+	      info->bmiColors[i].rgbBlue << 16;
+	}
+	PSDRV_WriteRGB(dc, map, 2);
+	PSDRV_WriteIndexColorSpaceEnd(dc);
+	break;
+
+    case 15:
+    case 16:
+    case 24:
+    case 32:
+      {
+	PSCOLOR pscol;
+	pscol.type = PSCOLOR_RGB;
+	pscol.value.rgb.r = pscol.value.rgb.g = pscol.value.rgb.b = 0.0;
+        PSDRV_WriteSetColor(dc, &pscol);
+        break;
+      }
+
+    default:
+        FIXME(psdrv, "Not implemented yet\n");
+	return FALSE;
+	break;
+    }
+
+    PSDRV_WriteImageDict(dc, info->bmiHeader.biBitCount, xDst, yDst,
+			  widthDst, heightDst, widthSrc, heightSrc);
+    return TRUE;
+}
 
 
 /***************************************************************************
  *
  *	PSDRV_StretchDIBits
+ *
+ * BUGS
+ *  Doesn't work correctly if the DIB bits aren't byte aligned at the start of
+ *  a line - this affects 1 and 4 bit depths.
+ *  Compression not implemented.
  */
 INT PSDRV_StretchDIBits( DC *dc, INT xDst, INT yDst, INT widthDst,
-			   INT heightDst, INT xSrc, INT ySrc,
-			   INT widthSrc, INT heightSrc, const void *bits,
-			   const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
+			 INT heightDst, INT xSrc, INT ySrc,
+			 INT widthSrc, INT heightSrc, const void *bits,
+			 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
 {
-    TRACE(psdrv, "(%d,%d %dx%d) -> (%d,%d %dx%d) on %08x. %d colour bits\n",
-	  xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst,
-	  dc->hSelf, info->bmiHeader.biBitCount);
+    DWORD fullSrcWidth;
+    INT widthbytes, fullSrcHeight;
+    WORD bpp, compression;
+    const char *ptr;
+    INT line;
+
+    TRACE(psdrv, "%08x (%d,%d %dx%d) -> (%d,%d %dx%d)\n", dc->hSelf,
+	  xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst);
+
+    DIB_GetBitmapInfo((const BITMAPINFOHEADER *)info, &fullSrcWidth,
+		      &fullSrcHeight, &bpp, &compression);
+
+    widthbytes = DIB_GetDIBWidthBytes(fullSrcWidth, bpp);
+
+    TRACE(psdrv, "full size=%ldx%d bpp=%d compression=%d\n", fullSrcWidth,
+	  fullSrcHeight, bpp, compression);
 
 
-    FIXME(psdrv, "stub\n");
-    return FALSE;
+    if(compression != BI_RGB) {
+        FIXME(psdrv, "Compression not supported\n");
+	return FALSE;
+    }
+
+
+    switch(bpp) {
+
+    case 1:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+	if(xSrc & 7 || widthSrc & 7)
+	    FIXME(psdrv, "This won't work...\n");
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteBytes(dc, ptr + xSrc/8, widthSrc/8);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    case 4:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+	if(xSrc & 1 || widthSrc & 1)
+	    FIXME(psdrv, "This won't work...\n");
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteBytes(dc, ptr + xSrc/2, widthSrc/2);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    case 8:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteBytes(dc, ptr + xSrc, widthSrc);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    case 15:
+    case 16:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteDIBits16(dc, (WORD *)ptr + xSrc, widthSrc);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    case 24:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteDIBits24(dc, ptr + xSrc * 3, widthSrc);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    case 32:
+	PSDRV_WriteGSave(dc);
+	PSDRV_WriteImageHeader(dc, info, xDst, yDst, widthDst, heightDst,
+			       widthSrc, heightSrc);
+
+	ptr = bits;
+	ptr += (ySrc * widthbytes);
+        for(line = 0; line < heightSrc; line++, ptr += widthbytes)
+	    PSDRV_WriteDIBits32(dc, ptr + xSrc * 3, widthSrc);
+	PSDRV_WriteGRestore(dc);
+	break;
+
+    default:
+        FIXME(psdrv, "Unsupported depth\n");
+	return FALSE;
+
+    }
+
+    return TRUE;
 }
+
+
+
+
+
+
diff --git a/graphics/psdrv/ps.c b/graphics/psdrv/ps.c
index b8d9ba2..3b1bd80 100644
--- a/graphics/psdrv/ps.c
+++ b/graphics/psdrv/ps.c
@@ -690,4 +690,167 @@
     return PSDRV_WriteSpool(dc, buf, strlen(buf));
 }
 
+BOOL PSDRV_WriteIndexColorSpaceBegin(DC *dc, int size)
+{
+    char buf[256];
+    sprintf(buf, "[/Indexed /DeviceRGB %d\n<\n", size);
+    return PSDRV_WriteSpool(dc, buf, strlen(buf));
+}
 
+BOOL PSDRV_WriteIndexColorSpaceEnd(DC *dc)
+{
+    char buf[] = ">\n] setcolorspace\n";
+    return PSDRV_WriteSpool(dc, buf, sizeof(buf) - 1);
+} 
+
+BOOL PSDRV_WriteRGB(DC *dc, COLORREF *map, int number)
+{
+    char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1), *ptr;
+    int i;
+
+    ptr = buf;
+    for(i = 0; i < number; i++) {
+        sprintf(ptr, "%02x%02x%02x%c", (int)GetRValue(map[i]), 
+		(int)GetGValue(map[i]), (int)GetBValue(map[i]),
+		((i & 0x7) == 0x7) || (i == number - 1) ? '\n' : ' ');
+	ptr += 7;
+    }
+    PSDRV_WriteSpool(dc, buf, number * 7);
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
+
+
+BOOL PSDRV_WriteImageDict(DC *dc, WORD depth, INT xDst, INT yDst,
+			  INT widthDst, INT heightDst, INT widthSrc,
+			  INT heightSrc)
+{
+    char start[] = "%d %d translate\n%d %d scale\n<<\n"
+      " /ImageType 1\n /Width %d\n /Height %d\n /BitsPerComponent %d\n"
+      " /ImageMatrix [%d 0 0 %d 0 %d]\n";
+
+    char decode1[] = " /Decode [0 %d]\n";
+    char decode3[] = " /Decode [0 1 0 1 0 1]\n";
+
+    char end[] = " /DataSource currentfile /ASCIIHexDecode filter\n>> image\n";
+
+    char *buf = HeapAlloc(PSDRV_Heap, 0, 1000);
+
+    sprintf(buf, start, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc,
+	    (depth < 8) ? depth : 8, widthSrc, -heightSrc, heightSrc);
+
+    PSDRV_WriteSpool(dc, buf, strlen(buf));
+
+    switch(depth) {
+    case 8:
+        sprintf(buf, decode1, 255);
+	break;
+
+    case 4:
+        sprintf(buf, decode1, 15);
+	break;
+
+    case 1:
+        sprintf(buf, decode1, 1);
+	break;
+
+    default:
+        strcpy(buf, decode3);
+	break;
+    }
+
+    PSDRV_WriteSpool(dc, buf, strlen(buf));
+
+    PSDRV_WriteSpool(dc, end, sizeof(end) - 1);
+
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
+
+BOOL PSDRV_WriteBytes(DC *dc, const BYTE *bytes, int number)
+{
+    char *buf = HeapAlloc(PSDRV_Heap, 0, number * 3 + 1);
+    char *ptr;
+    int i;
+    
+    ptr = buf;
+    
+    for(i = 0; i < number; i++) {
+        sprintf(ptr, "%02x%c", bytes[i],
+		((i & 0xf) == 0xf) || (i == number - 1) ? '\n' : ' ');
+	ptr += 3;
+    }
+    PSDRV_WriteSpool(dc, buf, number * 3);
+
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
+
+BOOL PSDRV_WriteDIBits16(DC *dc, const WORD *words, int number)
+{
+    char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1);
+    char *ptr;
+    int i;
+    
+    ptr = buf;
+    
+    for(i = 0; i < number; i++) {
+        int r, g, b;
+
+	/* We want 0x0 -- 0x1f to map to 0x0 -- 0xff */
+
+	r = words[i] >> 10 & 0x1f;
+	r = r << 3 | r >> 2;
+	g = words[i] >> 5 & 0x1f;
+	g = g << 3 | g >> 2;
+	b = words[i] & 0x1f;
+	b = b << 3 | b >> 2;
+        sprintf(ptr, "%02x%02x%02x%c", r, g, b,
+		((i & 0x7) == 0x7) || (i == number - 1) ? '\n' : ' ');
+	ptr += 7;
+    }
+    PSDRV_WriteSpool(dc, buf, number * 7);
+
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
+
+BOOL PSDRV_WriteDIBits24(DC *dc, const BYTE *bits, int number)
+{
+    char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1);
+    char *ptr;
+    int i;
+    
+    ptr = buf;
+    
+    for(i = 0; i < number; i++) {
+        sprintf(ptr, "%02x%02x%02x%c", bits[i * 3 + 2], bits[i * 3 + 1],
+		bits[i * 3],
+		((i & 0x7) == 0x7) || (i == number - 1) ? '\n' : ' ');
+	ptr += 7;
+    }
+    PSDRV_WriteSpool(dc, buf, number * 7);
+
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
+
+BOOL PSDRV_WriteDIBits32(DC *dc, const BYTE *bits, int number)
+{
+    char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1);
+    char *ptr;
+    int i;
+    
+    ptr = buf;
+    
+    for(i = 0; i < number; i++) {
+        sprintf(ptr, "%02x%02x%02x%c", bits[i * 4 + 2], bits[i * 4 + 1],
+		bits[i * 4],
+		((i & 0x7) == 0x7) || (i == number - 1) ? '\n' : ' ');
+	ptr += 7;
+    }
+    PSDRV_WriteSpool(dc, buf, number * 7);
+
+    HeapFree(PSDRV_Heap, 0, buf);
+    return TRUE;
+}
diff --git a/include/psdrv.h b/include/psdrv.h
index 3aa5946..3f27316 100644
--- a/include/psdrv.h
+++ b/include/psdrv.h
@@ -282,8 +282,16 @@
 extern BOOL PSDRV_WriteEOClip(DC *dc);
 extern BOOL PSDRV_WriteHatch(DC *dc);
 extern BOOL PSDRV_WriteRotate(DC *dc, float ang);
-
-
+extern BOOL PSDRV_WriteIndexColorSpaceBegin(DC *dc, int size);
+extern BOOL PSDRV_WriteIndexColorSpaceEnd(DC *dc);
+extern BOOL PSDRV_WriteRGB(DC *dc, COLORREF *map, int number);
+extern BOOL PSDRV_WriteImageDict(DC *dc, WORD depth, INT xDst, INT yDst,
+				 INT widthDst, INT heightDst, INT widthSrc,
+				 INT heightSrc);
+extern BOOL PSDRV_WriteBytes(DC *dc, const BYTE *bytes, int number);
+extern BOOL PSDRV_WriteDIBits16(DC *dc, const WORD *words, int number);
+extern BOOL PSDRV_WriteDIBits24(DC *dc, const BYTE *bits, int number);
+extern BOOL PSDRV_WriteDIBits32(DC *dc, const BYTE *bits, int number);