/*
 *	PostScript driver bitmap functions
 *
 * Copyright 1998  Huw D M Davies
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <assert.h>
#include <stdlib.h>

#include "psdrv.h"
#include "winbase.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(psdrv);


/* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. */
inline static int get_dib_width_bytes( int width, int depth )
{
    int words;

    switch(depth)
    {
    case 1:  words = (width + 31) / 32; break;
    case 4:  words = (width + 7) / 8; break;
    case 8:  words = (width + 3) / 4; break;
    case 15:
    case 16: words = (width + 1) / 2; break;
    case 24: words = (width * 3 + 3)/4; break;
    default:
        WARN("(%d): Unsupported depth\n", depth );
        /* fall through */
    case 32: words = width; break;
    }
    return 4 * words;
}

/* get the bitmap info from either an INFOHEADER or COREHEADER bitmap */
static BOOL get_bitmap_info( const void *ptr, LONG *width, LONG *height, WORD *bpp, WORD *compr )
{
    const BITMAPINFOHEADER *header = ptr;

    switch(header->biSize)
    {
    case sizeof(BITMAPCOREHEADER):
        {
            const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
            *width  = core->bcWidth;
            *height = core->bcHeight;
            *bpp    = core->bcBitCount;
            *compr  = 0;
        }
        return TRUE;
    case sizeof(BITMAPINFOHEADER):
    case sizeof(BITMAPV4HEADER):
    case sizeof(BITMAPV5HEADER):
        /* V4 and V5 structures are a superset of the INFOHEADER structure */
        *width  = header->biWidth;
        *height = header->biHeight;
        *bpp    = header->biBitCount;
        *compr  = header->biCompression;
        return TRUE;
    default:
        ERR("(%ld): unknown/wrong size for header\n", header->biSize );
        return FALSE;
    }
}


/***************************************************************************
 *                PSDRV_WriteImageHeader
 *
 * Helper for PSDRV_StretchDIBits
 *
 * BUGS
 *  Uses level 2 PostScript
 */

static BOOL PSDRV_WriteImageHeader(PSDRV_PDEVICE *physDev, 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(physDev, 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(physDev, map, 256);
	PSDRV_WriteIndexColorSpaceEnd(physDev);
	break;

    case 4:
        PSDRV_WriteIndexColorSpaceBegin(physDev, 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(physDev, map, 16);
	PSDRV_WriteIndexColorSpaceEnd(physDev);
	break;

    case 1:
        PSDRV_WriteIndexColorSpaceBegin(physDev, 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(physDev, map, 2);
	PSDRV_WriteIndexColorSpaceEnd(physDev);
	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(physDev, &pscol);
        break;
      }

    default:
        FIXME("Not implemented yet\n");
	return FALSE;
    }

    PSDRV_WriteImage(physDev, info->bmiHeader.biBitCount, xDst, yDst,
		     widthDst, heightDst, widthSrc, heightSrc, FALSE);
    return TRUE;
}


/***************************************************************************
 *                PSDRV_WriteImageMaskHeader
 *
 * Helper for PSDRV_StretchDIBits
 *
 * We use the imagemask operator for 1bpp bitmaps since the output
 * takes much less time for the printer to render.
 *
 * BUGS
 *  Uses level 2 PostScript
 */

static BOOL PSDRV_WriteImageMaskHeader(PSDRV_PDEVICE *physDev, const BITMAPINFO *info, INT xDst,
                                       INT yDst, INT widthDst, INT heightDst,
                                       INT widthSrc, INT heightSrc)
{
    COLORREF map[2];
    PSCOLOR bkgnd, foregnd;
    int i;

    assert(info->bmiHeader.biBitCount == 1);

    for(i = 0; i < 2; i++) {
        map[i] =  info->bmiColors[i].rgbRed |
            info->bmiColors[i].rgbGreen << 8 |
            info->bmiColors[i].rgbBlue << 16;
    }

    /* We'll write the mask with -ve polarity so that 
       the foregnd color corresponds to a bit equal to
       0 in the bitmap.
    */
    PSDRV_CreateColor(physDev, &foregnd, map[0]);
    PSDRV_CreateColor(physDev, &bkgnd, map[1]);

    PSDRV_WriteGSave(physDev);
    PSDRV_WriteNewPath(physDev);
    PSDRV_WriteRectangle(physDev, xDst, yDst, widthDst, heightDst);
    PSDRV_WriteSetColor(physDev, &bkgnd);
    PSDRV_WriteFill(physDev);
    PSDRV_WriteGRestore(physDev);

    PSDRV_WriteSetColor(physDev, &foregnd);
    PSDRV_WriteImage(physDev, 1, xDst, yDst, widthDst, heightDst,
		     widthSrc, heightSrc, TRUE);

    return TRUE;
}

static inline DWORD max_rle_size(DWORD size)
{
    return size + (size + 127) / 128 + 1;
}

static inline DWORD max_ascii85_size(DWORD size)
{
    return (size + 3) / 4 * 5;
}

/***************************************************************************
 *
 *	PSDRV_StretchDIBits
 *
 * BUGS
 *  Doesn't work correctly if xSrc isn't byte aligned - this affects 1 and 4
 *  bit depths.
 *  Compression not implemented.
 */
INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, 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 )
{
    LONG fullSrcWidth, fullSrcHeight;
    INT widthbytes;
    WORD bpp, compression;
    INT line;
    POINT pt[2];
    const BYTE *src_ptr;
    BYTE *dst_ptr, *bitmap, *rle, *ascii85;
    DWORD rle_len, ascii85_len, bitmap_size;

    TRACE("%p (%d,%d %dx%d) -> (%d,%d %dx%d)\n", physDev->hdc,
	  xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst);

    if (!get_bitmap_info( info, &fullSrcWidth, &fullSrcHeight, &bpp, &compression )) return FALSE;

    widthbytes = get_dib_width_bytes(fullSrcWidth, bpp);

    TRACE("full size=%ldx%ld bpp=%d compression=%d rop=%08lx\n", fullSrcWidth,
	  fullSrcHeight, bpp, compression, dwRop);


    if(compression != BI_RGB) {
        FIXME("Compression not supported\n");
	return FALSE;
    }

    pt[0].x = xDst;
    pt[0].y = yDst;
    pt[1].x = xDst + widthDst;
    pt[1].y = yDst + heightDst;
    LPtoDP( physDev->hdc, pt, 2 );
    xDst = pt[0].x;
    yDst = pt[0].y;
    widthDst = pt[1].x - pt[0].x;
    heightDst = pt[1].y - pt[0].y;

    switch(bpp) {

    case 1:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);

        /* Use imagemask rather than image */
	PSDRV_WriteImageMaskHeader(physDev, info, xDst, yDst, widthDst, heightDst,
                                   widthSrc, heightSrc);
	src_ptr = bits;
	src_ptr += (ySrc * widthbytes);
	if(xSrc & 7)
	    FIXME("This won't work...\n");
        bitmap_size = heightSrc * ((widthSrc + 7) / 8);
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += ((widthSrc + 7) / 8))
            memcpy(dst_ptr, src_ptr + xSrc / 8, (widthSrc + 7) / 8);
	break;

    case 4:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);
	PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
			       widthSrc, heightSrc);
	src_ptr = bits;
	src_ptr += (ySrc * widthbytes);
	if(xSrc & 1)
	    FIXME("This won't work...\n");
        bitmap_size = heightSrc * ((widthSrc + 1) / 2);
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += ((widthSrc + 1) / 2))
	    memcpy(dst_ptr, src_ptr + xSrc/2, (widthSrc+1)/2);
	break;

    case 8:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);
	PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
			       widthSrc, heightSrc);
	src_ptr = bits;
	src_ptr += (ySrc * widthbytes);
        bitmap_size = heightSrc * widthSrc;
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += widthSrc)
	    memcpy(dst_ptr, src_ptr + xSrc, widthSrc);
	break;

    case 15:
    case 16:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);
	PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
			       widthSrc, heightSrc);


        src_ptr = bits;
        src_ptr += (ySrc * widthbytes);
        bitmap_size = heightSrc * widthSrc * 3;
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) {
            const WORD *words = (const WORD *)src_ptr + xSrc;
            int i;
            for(i = 0; i < widthSrc; i++) {
                BYTE 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;
                dst_ptr[0] = r;
                dst_ptr[1] = g;
                dst_ptr[2] = b;
                dst_ptr += 3;
            }
        }
	break;

    case 24:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);
	PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
			       widthSrc, heightSrc);

        src_ptr = bits;
        src_ptr += (ySrc * widthbytes);
        bitmap_size = heightSrc * widthSrc * 3;
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) {
            const BYTE *byte = src_ptr + xSrc * 3;
            int i;
            for(i = 0; i < widthSrc; i++) {
                dst_ptr[0] = byte[i * 3 + 2];
                dst_ptr[1] = byte[i * 3 + 1];
                dst_ptr[2] = byte[i * 3];
                dst_ptr += 3;
            }
        }
	break;

    case 32:
        PSDRV_SetClip(physDev);
	PSDRV_WriteGSave(physDev);
	PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
			       widthSrc, heightSrc);

        src_ptr = bits;
        src_ptr += (ySrc * widthbytes);
        bitmap_size = heightSrc * widthSrc * 3;
        dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
        for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) {
            const BYTE *byte = src_ptr + xSrc * 4;
            int i;
            for(i = 0; i < widthSrc; i++) {
                dst_ptr[0] = byte[i * 4 + 2];
                dst_ptr[1] = byte[i * 4 + 1];
                dst_ptr[2] = byte[i * 4];
                dst_ptr += 3;
            }
        }
	break;

    default:
        FIXME("Unsupported depth\n");
	return FALSE;

    }

    rle = HeapAlloc(GetProcessHeap(), 0, max_rle_size(bitmap_size));
    rle_len = RLE_encode(bitmap, bitmap_size, rle);
    HeapFree(GetProcessHeap(), 0, bitmap);
    ascii85 = HeapAlloc(GetProcessHeap(), 0, max_ascii85_size(rle_len));
    ascii85_len = ASCII85_encode(rle, rle_len, ascii85);
    HeapFree(GetProcessHeap(), 0, rle);
    PSDRV_WriteData(physDev, ascii85, ascii85_len);
    HeapFree(GetProcessHeap(), 0, ascii85);
    PSDRV_WriteSpool(physDev, "~>\n", 3);
    PSDRV_WriteGRestore(physDev);
    PSDRV_ResetClip(physDev);
    return abs(heightSrc);
}
