Tacked GPL into comments. More hq4x tweaks.

This commit is contained in:
William Kendrick 2003-12-21 00:50:52 +00:00
parent 7487c3b31b
commit 8dee572c9d
8 changed files with 404 additions and 340 deletions

View file

@ -1,10 +1,26 @@
/* win32_print.c */
/* printing support for Tux Paint */
/* printing support for Tux Paint */
/* John Popplewell <john@johnnypops.demon.co.uk> */
/* John Popplewell <john@johnnypops.demon.co.uk> */
/* Sept. 30, 2002 - Oct. 17, 2002 */
/* Oct. 07, 2003 - added banding support */
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Sept. 30, 2002 - Oct. 17, 2002 */
/* Oct. 07, 2003 - added banding support */
/* - prints using 24-bit (not 32-bit) bitmap */
#include "SDL_syswm.h"
@ -17,243 +33,243 @@
#define MIR( id ) (MAKEINTRESOURCE( id ))
static PRINTDLG global_pd = {
sizeof(PRINTDLG),
NULL, NULL, NULL, NULL,
PD_RETURNDC,
0xFFFF,
0xFFFF,
0xFFFF,
0xFFFF,
1,
NULL,
};
static SDL_Surface *make24bitDIB( SDL_Surface *surf )
{
SDL_PixelFormat pixfmt;
SDL_Surface *surf24;
SDL_Surface *surfDIB;
Uint8 *src,*dst;
Uint32 linesize;
int i;
memset( &pixfmt, 0, sizeof(pixfmt) );
pixfmt.palette = NULL;
pixfmt.BitsPerPixel = 24;
pixfmt.BytesPerPixel= 3;
pixfmt.Rmask = 0x00FF0000;
pixfmt.Gmask = 0x0000FF00;
pixfmt.Bmask = 0x000000FF;
pixfmt.Amask = 0;
pixfmt.Rshift = 16;
pixfmt.Gshift = 8;
pixfmt.Bshift = 0;
pixfmt.Ashift = 0;
pixfmt.Rloss = 0;
pixfmt.Gloss = 0;
pixfmt.Bloss = 0;
pixfmt.Aloss = 0;
pixfmt.colorkey = 0;
pixfmt.alpha = 0;
surf24 = SDL_ConvertSurface( surf, &pixfmt, SDL_SWSURFACE );
surfDIB = SDL_CreateRGBSurface( SDL_SWSURFACE, surf24->w, surf24->h, 24,
pixfmt.Rmask, pixfmt.Gmask, pixfmt.Bmask, pixfmt.Amask );
linesize = surf24->w * 3; // Flip top2bottom
dst = surfDIB->pixels;
src = ((Uint8*)surf24->pixels)+((surf24->h-1)*surf24->pitch);
for ( i = 0; i < surf24->h; ++i )
{
memcpy( dst, src, linesize );
src -= surf24->pitch;
dst += surfDIB->pitch;
}
SDL_FreeSurface( surf24 ); // Free temp surface
return surfDIB;
}
/* returns 0 if failed */
static int GetDefaultPrinterStrings( char *device, char *driver, char *output )
{
char buff[MAX_PATH];
char *section = "windows";
char *key = "device";
char *def = "NODEFAULTPRINTER";
char *dev,*drv,*out;
if ( !GetProfileString( section, key, def, buff, sizeof(buff) ) )
return 0;
if ( strcmp( buff, def ) == 0 )
return 0;
if ( ((dev = strtok( buff, "," )) != NULL) &&
((drv = strtok( NULL, ", ")) != NULL) &&
((out = strtok( NULL, ", ")) != NULL) )
{
if ( device ) strcpy( device, dev );
if ( driver ) strcpy( driver, drv );
if ( output ) strcpy( output, out );
return 1;
}
return 0;
}
#define dmDeviceNameSize 32
static HANDLE LoadCustomPrinterHDEVMODE( HWND hWnd, const char *filepath )
{
char device[MAX_PATH];
HANDLE hPrinter = NULL;
int sizeof_devmode;
HGLOBAL hDevMode = NULL;
DEVMODE *devmode = NULL;
int res;
FILE *fp = NULL;
int block_size;
int block_read;
if ( (fp = fopen( filepath, "rb" )) == NULL )
return NULL;
if ( fread( device, 1, dmDeviceNameSize, fp ) != dmDeviceNameSize )
goto err_exit;
if (!OpenPrinter( device, &hPrinter, NULL ))
return NULL;
sizeof_devmode = (int)DocumentProperties( hWnd, hPrinter, device,
NULL, NULL, 0 );
if ( !sizeof_devmode )
goto err_exit;
hDevMode = GlobalAlloc( GHND, sizeof_devmode );
if ( !hDevMode )
goto err_exit;
devmode = (DEVMODE*)GlobalLock( hDevMode );
if ( !devmode )
goto err_exit;
res = DocumentProperties( hWnd, hPrinter, device, devmode, NULL,
DM_OUT_BUFFER);
if ( res != IDOK )
goto err_exit;
block_size = devmode->dmSize + devmode->dmDriverExtra;
block_read = fread( devmode, 1, block_size, fp );
if ( block_size != block_read )
goto err_exit;
fclose(fp);
res = DocumentProperties( hWnd, hPrinter, device, devmode, devmode,
DM_IN_BUFFER|DM_OUT_BUFFER);
if ( res != IDOK )
goto err_exit;
GlobalUnlock( hDevMode );
ClosePrinter( hPrinter );
return hDevMode;
err_exit:
if ( fp ) fclose( fp );
if ( devmode ) GlobalUnlock( hDevMode );
if ( hDevMode ) GlobalFree( hDevMode );
if ( hPrinter ) ClosePrinter( hPrinter );
return NULL;
}
static int SaveCustomPrinterHDEVMODE( HWND hWnd, const char *filepath, HANDLE hDevMode )
{
FILE *fp = NULL;
NOREF(hWnd);
if ( (fp = fopen( filepath, "wb" )) != NULL )
{
DEVMODE *devmode = (DEVMODE*)GlobalLock( hDevMode );
int block_size = devmode->dmSize + devmode->dmDriverExtra;
int block_written;
char devname[dmDeviceNameSize];
strcpy( devname, (const char*)devmode->dmDeviceName );
fwrite( devname, 1, sizeof(devname), fp );
block_written = fwrite( devmode, 1, block_size, fp );
GlobalUnlock( hDevMode );
fclose( fp );
return block_size == block_written;
}
return 0;
}
static HDC GetCustomPrinterDC( HWND hWnd, const char *printcfg, int show )
{
global_pd.hwndOwner = hWnd;
global_pd.hDC = NULL;
global_pd.hDevNames = NULL;
if ( global_pd.hDevMode == NULL )
{
global_pd.hDevMode = LoadCustomPrinterHDEVMODE( hWnd, printcfg );
}
if ( show )
{
if ( PrintDlg( &global_pd ) )
{
SaveCustomPrinterHDEVMODE( hWnd, printcfg, global_pd.hDevMode );
return global_pd.hDC;
}
return NULL;
}
{
DEVMODE *devmode = (DEVMODE*)GlobalLock( global_pd.hDevMode );
global_pd.hDC = CreateDC( NULL, (const char*)devmode->dmDeviceName, NULL, devmode );
GlobalUnlock( global_pd.hDevMode );
}
return global_pd.hDC;
}
static HDC GetDefaultPrinterDC( void )
{
char device[MAX_PATH],driver[MAX_PATH],output[MAX_PATH];
if ( GetDefaultPrinterStrings( device, driver, output ) )
return CreateDC( driver, device, output, NULL );
return NULL;
}
static HDC GetPrinterDC( HWND hWnd, const char *printcfg, int show )
{
if ( !printcfg ) return GetDefaultPrinterDC();
return GetCustomPrinterDC( hWnd, printcfg, show );
}
static int IsBandingRequired( HDC hPrinter )
{
OSVERSIONINFO osvi;
int indata = NEXTBAND;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if ( GetVersionEx( &osvi ) && (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) )
return Escape( hPrinter, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&indata, NULL );
return 0;
}
static PRINTDLG global_pd = {
sizeof(PRINTDLG),
NULL, NULL, NULL, NULL,
PD_RETURNDC,
0xFFFF,
0xFFFF,
0xFFFF,
0xFFFF,
1,
NULL,
};
static SDL_Surface *make24bitDIB( SDL_Surface *surf )
{
SDL_PixelFormat pixfmt;
SDL_Surface *surf24;
SDL_Surface *surfDIB;
Uint8 *src,*dst;
Uint32 linesize;
int i;
memset( &pixfmt, 0, sizeof(pixfmt) );
pixfmt.palette = NULL;
pixfmt.BitsPerPixel = 24;
pixfmt.BytesPerPixel= 3;
pixfmt.Rmask = 0x00FF0000;
pixfmt.Gmask = 0x0000FF00;
pixfmt.Bmask = 0x000000FF;
pixfmt.Amask = 0;
pixfmt.Rshift = 16;
pixfmt.Gshift = 8;
pixfmt.Bshift = 0;
pixfmt.Ashift = 0;
pixfmt.Rloss = 0;
pixfmt.Gloss = 0;
pixfmt.Bloss = 0;
pixfmt.Aloss = 0;
pixfmt.colorkey = 0;
pixfmt.alpha = 0;
surf24 = SDL_ConvertSurface( surf, &pixfmt, SDL_SWSURFACE );
surfDIB = SDL_CreateRGBSurface( SDL_SWSURFACE, surf24->w, surf24->h, 24,
pixfmt.Rmask, pixfmt.Gmask, pixfmt.Bmask, pixfmt.Amask );
linesize = surf24->w * 3; // Flip top2bottom
dst = surfDIB->pixels;
src = ((Uint8*)surf24->pixels)+((surf24->h-1)*surf24->pitch);
for ( i = 0; i < surf24->h; ++i )
{
memcpy( dst, src, linesize );
src -= surf24->pitch;
dst += surfDIB->pitch;
}
SDL_FreeSurface( surf24 ); // Free temp surface
return surfDIB;
}
/* returns 0 if failed */
static int GetDefaultPrinterStrings( char *device, char *driver, char *output )
{
char buff[MAX_PATH];
char *section = "windows";
char *key = "device";
char *def = "NODEFAULTPRINTER";
char *dev,*drv,*out;
if ( !GetProfileString( section, key, def, buff, sizeof(buff) ) )
return 0;
if ( strcmp( buff, def ) == 0 )
return 0;
if ( ((dev = strtok( buff, "," )) != NULL) &&
((drv = strtok( NULL, ", ")) != NULL) &&
((out = strtok( NULL, ", ")) != NULL) )
{
if ( device ) strcpy( device, dev );
if ( driver ) strcpy( driver, drv );
if ( output ) strcpy( output, out );
return 1;
}
return 0;
}
#define dmDeviceNameSize 32
static HANDLE LoadCustomPrinterHDEVMODE( HWND hWnd, const char *filepath )
{
char device[MAX_PATH];
HANDLE hPrinter = NULL;
int sizeof_devmode;
HGLOBAL hDevMode = NULL;
DEVMODE *devmode = NULL;
int res;
FILE *fp = NULL;
int block_size;
int block_read;
if ( (fp = fopen( filepath, "rb" )) == NULL )
return NULL;
if ( fread( device, 1, dmDeviceNameSize, fp ) != dmDeviceNameSize )
goto err_exit;
if (!OpenPrinter( device, &hPrinter, NULL ))
return NULL;
sizeof_devmode = (int)DocumentProperties( hWnd, hPrinter, device,
NULL, NULL, 0 );
if ( !sizeof_devmode )
goto err_exit;
hDevMode = GlobalAlloc( GHND, sizeof_devmode );
if ( !hDevMode )
goto err_exit;
devmode = (DEVMODE*)GlobalLock( hDevMode );
if ( !devmode )
goto err_exit;
res = DocumentProperties( hWnd, hPrinter, device, devmode, NULL,
DM_OUT_BUFFER);
if ( res != IDOK )
goto err_exit;
block_size = devmode->dmSize + devmode->dmDriverExtra;
block_read = fread( devmode, 1, block_size, fp );
if ( block_size != block_read )
goto err_exit;
fclose(fp);
res = DocumentProperties( hWnd, hPrinter, device, devmode, devmode,
DM_IN_BUFFER|DM_OUT_BUFFER);
if ( res != IDOK )
goto err_exit;
GlobalUnlock( hDevMode );
ClosePrinter( hPrinter );
return hDevMode;
err_exit:
if ( fp ) fclose( fp );
if ( devmode ) GlobalUnlock( hDevMode );
if ( hDevMode ) GlobalFree( hDevMode );
if ( hPrinter ) ClosePrinter( hPrinter );
return NULL;
}
static int SaveCustomPrinterHDEVMODE( HWND hWnd, const char *filepath, HANDLE hDevMode )
{
FILE *fp = NULL;
NOREF(hWnd);
if ( (fp = fopen( filepath, "wb" )) != NULL )
{
DEVMODE *devmode = (DEVMODE*)GlobalLock( hDevMode );
int block_size = devmode->dmSize + devmode->dmDriverExtra;
int block_written;
char devname[dmDeviceNameSize];
strcpy( devname, (const char*)devmode->dmDeviceName );
fwrite( devname, 1, sizeof(devname), fp );
block_written = fwrite( devmode, 1, block_size, fp );
GlobalUnlock( hDevMode );
fclose( fp );
return block_size == block_written;
}
return 0;
}
static HDC GetCustomPrinterDC( HWND hWnd, const char *printcfg, int show )
{
global_pd.hwndOwner = hWnd;
global_pd.hDC = NULL;
global_pd.hDevNames = NULL;
if ( global_pd.hDevMode == NULL )
{
global_pd.hDevMode = LoadCustomPrinterHDEVMODE( hWnd, printcfg );
}
if ( show )
{
if ( PrintDlg( &global_pd ) )
{
SaveCustomPrinterHDEVMODE( hWnd, printcfg, global_pd.hDevMode );
return global_pd.hDC;
}
return NULL;
}
{
DEVMODE *devmode = (DEVMODE*)GlobalLock( global_pd.hDevMode );
global_pd.hDC = CreateDC( NULL, (const char*)devmode->dmDeviceName, NULL, devmode );
GlobalUnlock( global_pd.hDevMode );
}
return global_pd.hDC;
}
static HDC GetDefaultPrinterDC( void )
{
char device[MAX_PATH],driver[MAX_PATH],output[MAX_PATH];
if ( GetDefaultPrinterStrings( device, driver, output ) )
return CreateDC( driver, device, output, NULL );
return NULL;
}
static HDC GetPrinterDC( HWND hWnd, const char *printcfg, int show )
{
if ( !printcfg ) return GetDefaultPrinterDC();
return GetCustomPrinterDC( hWnd, printcfg, show );
}
static int IsBandingRequired( HDC hPrinter )
{
OSVERSIONINFO osvi;
int indata = NEXTBAND;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if ( GetVersionEx( &osvi ) && (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) )
return Escape( hPrinter, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&indata, NULL );
return 0;
}
int IsPrinterAvailable( void )
{
return (GetDefaultPrinterStrings( NULL, NULL, NULL ) != 0);
@ -267,8 +283,8 @@ const char *SurfacePrint( SDL_Surface *surf, const char *printcfg, int showdialo
DOCINFO di;
int nError;
SDL_SysWMinfo wminfo;
HDC hDCwindow;
HDC hDCprinter;
HDC hDCwindow;
HDC hDCprinter;
BITMAPINFOHEADER bmih;
SDL_Surface *surf24 = NULL;
RECT rc;
@ -278,17 +294,17 @@ const char *SurfacePrint( SDL_Surface *surf, const char *printcfg, int showdialo
float subscaler,subscalerx,subscalery;
int hDCCaps;
HBITMAP hbm = NULL;
HDC hdcMem = NULL;
HDC hdcMem = NULL;
SDL_VERSION(&wminfo.version);
if ( !SDL_GetWMInfo( &wminfo ) )
return "win32_print: SDL_GetWMInfo() failed.";
return "win32_print: SDL_GetWMInfo() failed.";
hWnd = wminfo.window;
hDCprinter = GetPrinterDC( hWnd, printcfg, showdialog );
if ( !hDCprinter )
return "win32_print: GetPrinterDC() failed.";
hDCprinter = GetPrinterDC( hWnd, printcfg, showdialog );
if ( !hDCprinter )
return "win32_print: GetPrinterDC() failed.";
EnableWindow( hWnd, FALSE );
di.cbSize = sizeof(DOCINFO);
@ -313,21 +329,21 @@ const char *SurfacePrint( SDL_Surface *surf, const char *printcfg, int showdialo
//////////////////////////////////////////////////////////////////////////////////////
surf24 = make24bitDIB( surf );
surf24 = make24bitDIB( surf );
if ( !surf24 )
{
res = "win32_print: make24bitDIB() failed.";
goto error;
}
memset( &bmih,0, sizeof(bmih) );
bmih.biSize = sizeof(bmih);
bmih.biPlanes = 1;
bmih.biCompression = BI_RGB;
bmih.biBitCount = 24;
bmih.biWidth = surf24->w;
bmih.biHeight = surf24->h;
memset( &bmih,0, sizeof(bmih) );
bmih.biSize = sizeof(bmih);
bmih.biPlanes = 1;
bmih.biCompression = BI_RGB;
bmih.biBitCount = 24;
bmih.biWidth = surf24->w;
bmih.biHeight = surf24->h;
GetClientRect( hWnd, &rc );
subscalerx = (float)rc.right/surf24->w;
subscalery = (float)rc.bottom/surf24->h;
@ -335,15 +351,15 @@ const char *SurfacePrint( SDL_Surface *surf, const char *printcfg, int showdialo
if ( subscalerx < subscalery )
subscaler = subscalerx;
hDCwindow = GetDC( hWnd );
if ( !hDCwindow )
{
res = "win32_print: failed to get window DC.";
goto error;
}
hDCwindow = GetDC( hWnd );
if ( !hDCwindow )
{
res = "win32_print: failed to get window DC.";
goto error;
}
fLogPelsX1 = (float)GetDeviceCaps(hDCwindow, LOGPIXELSX);
fLogPelsY1 = (float)GetDeviceCaps(hDCwindow, LOGPIXELSY);
ReleaseDC( hWnd, hDCwindow );
ReleaseDC( hWnd, hDCwindow );
fLogPelsX2 = (float)GetDeviceCaps(hDCprinter, LOGPIXELSX);
fLogPelsY2 = (float)GetDeviceCaps(hDCprinter, LOGPIXELSY);
@ -368,69 +384,69 @@ const char *SurfacePrint( SDL_Surface *surf, const char *printcfg, int showdialo
hDCCaps = GetDeviceCaps(hDCprinter, RASTERCAPS);
if (hDCCaps & RC_PALETTE)
{
res = "win32_print: printer context requires palette.";
goto error;
}
if ( IsBandingRequired( hDCprinter ) )
{
RECT rcBand = { 0 };
RECT rcPrinter;
RECT rcImage;
SetRect( &rcPrinter, xLeft, yTop, (int)(fScaleX*bmih.biWidth), (int)(fScaleY*bmih.biHeight) );
SetRect( &rcImage, 0, 0, bmih.biWidth, bmih.biHeight );
while ( Escape(hDCprinter, NEXTBAND, 0, NULL, &rcBand) )
{
if ( IsRectEmpty( &rcBand) ) break;
if ( IntersectRect( &rcBand, &rcBand, &rcPrinter ) )
{
rcImage.top = (int)(0.5f+(float)rcBand.top/fScaleX);
rcImage.bottom = (int)(0.5f+(float)rcBand.bottom/fScaleX);
SetStretchBltMode( hDCprinter, COLORONCOLOR );
nError = StretchDIBits(hDCprinter, rcBand.left, rcBand.top,
rcBand.right - rcBand.left,
rcBand.bottom - rcBand.top,
rcImage.left, rcImage.top,
rcImage.right - rcImage.left,
rcImage.bottom - rcImage.top,
surf24->pixels, (BITMAPINFO*)&bmih,
DIB_RGB_COLORS, SRCCOPY);
if ( nError == GDI_ERROR )
{
res = "win32_print: StretchDIBits() failed.";
goto error;
}
}
}
}
else
{
if (hDCCaps & RC_PALETTE)
{
res = "win32_print: printer context requires palette.";
goto error;
}
if ( IsBandingRequired( hDCprinter ) )
{
RECT rcBand = { 0 };
RECT rcPrinter;
RECT rcImage;
SetRect( &rcPrinter, xLeft, yTop, (int)(fScaleX*bmih.biWidth), (int)(fScaleY*bmih.biHeight) );
SetRect( &rcImage, 0, 0, bmih.biWidth, bmih.biHeight );
while ( Escape(hDCprinter, NEXTBAND, 0, NULL, &rcBand) )
{
if ( IsRectEmpty( &rcBand) ) break;
if ( IntersectRect( &rcBand, &rcBand, &rcPrinter ) )
{
rcImage.top = (int)(0.5f+(float)rcBand.top/fScaleX);
rcImage.bottom = (int)(0.5f+(float)rcBand.bottom/fScaleX);
SetStretchBltMode( hDCprinter, COLORONCOLOR );
nError = StretchDIBits(hDCprinter, rcBand.left, rcBand.top,
rcBand.right - rcBand.left,
rcBand.bottom - rcBand.top,
rcImage.left, rcImage.top,
rcImage.right - rcImage.left,
rcImage.bottom - rcImage.top,
surf24->pixels, (BITMAPINFO*)&bmih,
DIB_RGB_COLORS, SRCCOPY);
if ( nError == GDI_ERROR )
{
res = "win32_print: StretchDIBits() failed.";
goto error;
}
}
}
}
else
{
if ( hDCCaps & RC_STRETCHDIB )
{
SetStretchBltMode(hDCprinter, COLORONCOLOR);
SetStretchBltMode(hDCprinter, COLORONCOLOR);
nError = StretchDIBits(hDCprinter, xLeft, yTop,
(int)(fScaleX*bmih.biWidth),
(int)(fScaleY*bmih.biHeight),
0, 0, bmih.biWidth, bmih.biHeight,
surf24->pixels, (BITMAPINFO*)&bmih,
DIB_RGB_COLORS, SRCCOPY);
if ( nError == GDI_ERROR )
{
res = "win32_print: StretchDIBits() failed.";
goto error;
DIB_RGB_COLORS, SRCCOPY);
if ( nError == GDI_ERROR )
{
res = "win32_print: StretchDIBits() failed.";
goto error;
}
}
else
{
res = "win32_print: StretchDIBits() not available.";
goto error;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
@ -450,7 +466,7 @@ error:
if ( surf24 ) SDL_FreeSurface( surf24 );
EnableWindow( hWnd, TRUE );
DeleteDC( hDCprinter );
DeleteDC( hDCprinter );
return res;
}