Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3427 lines
82 KiB

#include <platform.h>
#include <sccut.h>
#include <sccch.h>
#include <sccvw.h>
#include <sccd.h>
#include "oibnp_w.h"
#include "oibde.h"
#include "oibdlgs.h"
#include "oibstr.h"
#include "oibde.pro"
#include "oibnp_w.pro"
/*
| --------- GLOBALS -------------------------------------------
*/
WORD rMap[256];
WORD gMap[256];
WORD bMap[256];
BYTE szFullScreenClassName[] = "OIBFullScreen";
HANDLE staticHPrintSample;
extern BITMAPOPT Options;
/*
| --------- ROUTINES USED BY OIBDE.C---------------------------
*/
WORD BUGetScreenColors( hdc )
HDC hdc;
{
WORD wRastaMon;
if( 24 != GetDeviceCaps(hdc, BITSPIXEL) )
{
wRastaMon = GetDeviceCaps(hdc, RASTERCAPS);
if( wRastaMon & RC_PALETTE )
return( GetDeviceCaps(hdc, SIZEPALETTE) );
else
return( GetDeviceCaps(hdc, NUMCOLORS) );
}
else
return 0; // True color.
}
/*
| This routine performs any platform-specific initialization.
*/
VOID OIBNPPlatformInit()
{
// Set up the 24-bit to 256 color lookup tables....
OIBWGenTrueColorMap();
}
/*
| OIBNPInitBitmapInfo:
|
| Initializes a platform specific bitmap information structure.
| Stores a handle to this structure in lpDisplay->Image.Np.hDocBmpInfo.
*/
VOID OIBNPInitBitmapInfo( lpDisplay, pSecInfo )
POIB_DISPLAY lpDisplay;
PCHSECTIONINFO pSecInfo;
{
HANDLE hInfo;
LPBITMAPINFO lpInfo;
DWORD dwInfoSize;
LPSTR lpDocPal;
// Calculate the total size of the BITMAPINFO structure.
dwInfoSize = sizeof(BITMAPINFOHEADER);
// Add the size of the palette to dwInfoSize.
if( pSecInfo->Attr.Bitmap.bmpHeader.wBitsPerPixel != 24 )
dwInfoSize += sizeof(RGBQUAD) * (1 << pSecInfo->Attr.Bitmap.bmpHeader.wBitsPerPixel);
hInfo = UTGlobalAlloc( dwInfoSize );
if( hInfo == NULL )
; // We're screwed.
lpInfo = (LPBITMAPINFO) GlobalLock( hInfo );
lpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpInfo->bmiHeader.biBitCount = pSecInfo->Attr.Bitmap.bmpHeader.wBitsPerPixel;
lpInfo->bmiHeader.biPlanes = 1;
lpInfo->bmiHeader.biCompression = BI_RGB;
lpInfo->bmiHeader.biClrUsed = pSecInfo->Attr.Bitmap.wPalEntries;
if( pSecInfo->Attr.Bitmap.wPalEntries )
{
// Copy the document's palette info.
// Luckily, it's stored in identical structures to windows' RGBQUADs.
lpDocPal = UTGlobalLock( pSecInfo->Attr.Bitmap.hPalInfo );
UTmemcpy( (LPSTR)&(lpInfo->bmiColors), lpDocPal, pSecInfo->Attr.Bitmap.wPalEntries * sizeof(RGBQUAD) );
UTGlobalUnlock( pSecInfo->Attr.Bitmap.hPalInfo );
}
UTGlobalUnlock( hInfo );
lpDisplay->Image.Np.hDocBmpInfo = hInfo;
}
VOID OIBNPPlatformDeInit( lpDisplay )
POIB_DISPLAY lpDisplay;
{
if( lpDisplay->Image.Np.hDisplayBmpInfo != lpDisplay->Image.Np.hDocBmpInfo )
GlobalFree( lpDisplay->Image.Np.hDisplayBmpInfo );
GlobalFree( lpDisplay->Image.Np.hDocBmpInfo );
lpDisplay->Image.Np.hDocBmpInfo = NULL;
lpDisplay->Image.Np.hDisplayBmpInfo = NULL;
if( lpDisplay->hDitherBuf != NULL )
{
LocalFree(lpDisplay->hDitherBuf);
lpDisplay->hDitherBuf = NULL;
}
if( lpDisplay->hColorBuf != NULL )
{
LocalFree(lpDisplay->hColorBuf);
lpDisplay->hColorBuf = NULL;
}
}
#ifdef SCCFEATURE_SCALING
BOOL OIBNPScaleRect(hdc,pr,lpd)
HDC hdc;
LPRECT pr;
POIB_DISPLAY lpd;
{
SOPOINT Tmp[2];
Tmp[0].x = (SHORT)pr->left;
Tmp[0].y = (SHORT)pr->top;
Tmp[1].x = (SHORT)pr->right;
Tmp[1].y = (SHORT)pr->bottom;
OIBNPScale(hdc,Tmp,2,lpd);
pr->left = Tmp[0].x;
pr->top = Tmp[0].y;
pr->right = Tmp[1].x;
pr->bottom = Tmp[1].y;
return(1);
}
BOOL OIBNPReverseScaleRect(hdc,pr,lpd)
HDC hdc;
LPRECT pr;
POIB_DISPLAY lpd;
{
SOPOINT Tmp[2];
Tmp[0].x = (SHORT)pr->left;
Tmp[0].y = (SHORT)pr->top;
Tmp[1].x = (SHORT)pr->right;
Tmp[1].y = (SHORT)pr->bottom;
OIBNPReverseScale(hdc,Tmp,2,lpd);
pr->left = Tmp[0].x;
pr->top = Tmp[0].y;
pr->right = Tmp[1].x;
pr->bottom = Tmp[1].y;
return(1);
}
#endif //SCCFEATURE_SCALING
/*
| OIBNPInitPalette:
|
| Creates the palette, if needed.
| Stores a handle to the palette in lpDisplay->Image.hPalette.
| Returns the number of colors in the palette.
*/
WORD OIBNPInitPalette( lpDisplay, pSecInfo )
POIB_DISPLAY lpDisplay;
PCHSECTIONINFO pSecInfo;
{
LPBITMAPINFO lpInfo;
LPRGBQUAD pSrcEntry;
LPPALETTEENTRY pNewEntry;
LPLOGPALETTE lpPalette;
WORD i;
WORD wNumColors;
HDC hdc;
hdc = lpDisplay->Gen.hDC;
lpInfo = (LPBITMAPINFO) GlobalLock( lpDisplay->Image.Np.hDocBmpInfo );
if( lpInfo->bmiHeader.biBitCount == 24 )
{
if( lpDisplay->wScreenColors == 256 )
{
// wNumColors = 256;
wNumColors = 216; // Testing the new splash palette
lpDisplay->wFlags |= (OIBF_TRUECOLORTO256 | OIBF_DITHERABLE);
}
else
{
lpDisplay->Image.hPalette = NULL;
wNumColors = 0;
if( lpDisplay->wScreenColors == 16 )
{
lpDisplay->wFlags |= OIBF_DITHERABLE;
if( lpDisplay->bDither )
{
wNumColors = 16;
lpDisplay->wFlags |= OIBF_DITHER4BIT;
}
}
}
}
else
{
wNumColors = (WORD) lpInfo->bmiHeader.biClrUsed;
if( wNumColors == 0 )
wNumColors = 1 << lpInfo->bmiHeader.biBitCount;
#ifdef SCCFEATURE_DITHER
if( lpDisplay->wScreenColors == 16 &&
(wNumColors > 16 || !OIBWCheckDefaultPalette(lpInfo, wNumColors)) )
{
lpDisplay->wFlags |= OIBF_DITHERABLE;
if(lpDisplay->bDither)
{
wNumColors = 16;
lpDisplay->wFlags |= OIBF_DITHER4BIT;
}
}
#endif
}
if( wNumColors )
{
if( !(lpDisplay->wFlags & OIBF_LOGPALETTEALLOCATED ))
{
lpDisplay->hPalMem = LocalAlloc( LMEM_ZEROINIT | LMEM_FIXED, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors );
lpPalette = (LPLOGPALETTE) LocalLock(lpDisplay->hPalMem);
lpDisplay->wFlags |= OIBF_LOGPALETTEALLOCATED;
lpPalette->palVersion = 0x0300;
lpPalette->palNumEntries = wNumColors;
pNewEntry = (LPPALETTEENTRY) &(lpPalette->palPalEntry);
if( lpDisplay->wFlags & OIBF_TRUECOLORTO256 )
OIBWGenDefault256Palette( lpInfo, hdc, pNewEntry );
#ifdef SCCFEATURE_DITHER
else if( lpDisplay->wFlags & OIBF_DITHER4BIT )
{
// Dither stuff: get and use the system palette.
OIBWGetDefault16Palette( pNewEntry );
}
#endif
else
{
pSrcEntry = (LPRGBQUAD) &(lpInfo->bmiColors);
for( i=0; i < wNumColors; i++ )
{
pNewEntry[i].peRed = pSrcEntry[i].rgbRed;
pNewEntry[i].peGreen = pSrcEntry[i].rgbGreen;
pNewEntry[i].peBlue = pSrcEntry[i].rgbBlue;
//pNewEntry[i].peFlags = PC_NOCOLLAPSE;
pNewEntry[i].peFlags = 0;
}
}
}
else
lpPalette = (LPLOGPALETTE) LocalLock(lpDisplay->hPalMem);
lpDisplay->Image.hPalette = CreatePalette(lpPalette);
LocalUnlock(lpDisplay->hPalMem);
}
if( lpDisplay->Image.hPalette == NULL )
{
// CreatePalette failed, or image is true color.
// (Can't use the logical palette stuff.)
wNumColors = 0;
lpDisplay->Image.wCreateBmpFlags = DIB_RGB_COLORS;
lpDisplay->Image.Np.hDisplayBmpInfo = lpDisplay->Image.Np.hDocBmpInfo;
}
else if(!(lpDisplay->wFlags & OIBF_LOGPALINFOALLOCATED))
{
LPWORD pwPalEnt;
LPBITMAPINFO lpInfo2;
// Let's allocate a new info structure that's set up for a logical palette.
// This logical palette (hopefully) will speed up display, and will be
// used when dithering images that have more colors than the system.
// We want to keep our original info structure around though, with its
// RGB values, for better printing and DIB support on the clipboard.
lpDisplay->Image.wCreateBmpFlags = DIB_PAL_COLORS;
lpDisplay->Image.Np.hDisplayBmpInfo = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER) + wNumColors * sizeof(WORD) );
lpInfo2 = (LPBITMAPINFO) GlobalLock(lpDisplay->Image.Np.hDisplayBmpInfo);
lpInfo2->bmiHeader = lpInfo->bmiHeader;
pwPalEnt = (LPWORD) lpInfo2->bmiColors;
for( i=0; i < wNumColors; i++ )
pwPalEnt[i] = i;
GlobalUnlock( lpDisplay->Image.Np.hDisplayBmpInfo );
lpDisplay->wFlags |= OIBF_LOGPALINFOALLOCATED;
}
GlobalUnlock( lpDisplay->Image.Np.hDocBmpInfo );
if( lpDisplay->Image.hPalette != NULL && hdc != NULL)
{
// hdc test added by PJB because this functions gets called in DISPLAYOPEN
// and lpDisplay->Gen.hDC is NULL on DISPLAYOPEN.
// Select palette one time with the 'bForceBackground' parameter set FALSE.
// This ensures that the first time the image is displayed it will use
// its own palette. All other palette selection will be done with
// bForceBackground set to TRUE, and Windows will decide what palette is used.
HPALETTE hOldPal;
hOldPal = SelectPalette( hdc, lpDisplay->Image.hPalette, FALSE );
RealizePalette( hdc );
SelectPalette( hdc, hOldPal, TRUE );
}
return( wNumColors );
}
#ifdef SCCFEATURE_MENU
WORD OIBNPFillMenu( hMenu, wCommandOffset )
HMENU hMenu;
WORD wCommandOffset;
{
/* JKXXX
HMENU hPopup;
BYTE MenuString[OIB_MENUSTRINGMAX];
WORD i;
WORD wMag;
LoadString( hInst, OIBSTR_SHOWFULL, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hMenu, MF_STRING, wCommandOffset + OIBMENU_SHOWFULLSCREEN, MenuString );
hPopup = CreatePopupMenu();
if( hPopup == NULL )
return 0;
LoadString( hInst, OIBSTR_NOSCALING, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, (Options.wScaleMode == OIBMENU_NOSCALING) ? MF_CHECKED|MF_STRING : MF_STRING , wCommandOffset + OIBMENU_NOSCALING, MenuString );
LoadString( hInst, OIBSTR_TOWINDOW, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, (Options.wScaleMode == OIBMENU_SCALETOWINDOW) ? MF_CHECKED|MF_STRING : MF_STRING , wCommandOffset + OIBMENU_SCALETOWINDOW, MenuString );
LoadString( hInst, OIBSTR_TOWIDTH, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, (Options.wScaleMode == OIBMENU_SCALETOWIDTH) ? MF_CHECKED|MF_STRING : MF_STRING, wCommandOffset + OIBMENU_SCALETOWIDTH, MenuString );
LoadString( hInst, OIBSTR_TOHEIGHT, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, (Options.wScaleMode == OIBMENU_SCALETOHEIGHT) ? MF_CHECKED|MF_STRING : MF_STRING, wCommandOffset + OIBMENU_SCALETOHEIGHT, MenuString );
LoadString( hInst, OIBSTR_SIZE, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hMenu, MF_POPUP|MF_STRING, (WORD)hPopup, MenuString );
hPopup = CreatePopupMenu();
if( hPopup == NULL )
return 0;
wMag = wCommandOffset + OIBMENU_MAGNIFYPOPUP+1;
for( i=0; i<OIB_MAXZOOM; i++ )
{
wsprintf( (LPSTR) MenuString, "&%d:1", i+1 );
AppendMenu( hPopup, MF_STRING, wMag++, (LPSTR)MenuString );
}
LoadString( hInst, OIBSTR_MAGNIFY, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hMenu, MF_POPUP|MF_STRING, (WORD)hPopup, MenuString );
hPopup = CreatePopupMenu();
if( hPopup == NULL )
return 0;
LoadString( hInst, OIBSTR_NOROTATION, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, MF_CHECKED|MF_STRING, wCommandOffset + OIBMENU_NOROTATION, MenuString );
LoadString( hInst, OIBSTR_ROTATE90, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, MF_STRING, wCommandOffset + OIBMENU_ROTATE90, MenuString );
LoadString( hInst, OIBSTR_ROTATE180, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, MF_STRING, wCommandOffset + OIBMENU_ROTATE180, MenuString );
LoadString( hInst, OIBSTR_ROTATE270, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hPopup, MF_STRING, wCommandOffset + OIBMENU_ROTATE270, MenuString );
LoadString( hInst, OIBSTR_ROTATION, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hMenu, MF_POPUP|MF_STRING, (WORD)hPopup, MenuString );
LoadString( hInst, OIBSTR_DITHER, MenuString, OIB_MENUSTRINGMAX );
AppendMenu( hMenu, (Options.bDither) ? MF_CHECKED|MF_STRING : MF_STRING , wCommandOffset + OIBMENU_DITHER, MenuString );
*/
return 1;
}
#endif // SCCFEATURE_MENU
#ifdef NEVER
#ifdef SCCFEATURE_MENU
VOID OIBNPUpdateMagMenu( lpDisplay, wOldMag )
POIB_DISPLAY lpDisplay;
WORD wOldMag;
{
HMENU hMagPopup; // handle to the magnification menu.
hMagPopup = GetSubMenu( lpDisplay->Gen.hDisplayMenu, OIB_MAGPOPUPPOS );
// Clear the current magnification menu checkmark
if( lpDisplay->wNumMagItems > OIB_MAXZOOM )
{
// Zoom selection usually is a non-integral magnification, which
// causes an extra item to be inserted into the magnification menu.
DeleteMenu( hMagPopup, OIBMENU_CUSTOMMAG, MF_BYCOMMAND );
lpDisplay->wNumMagItems--;
}
else
CheckMenuItem( hMagPopup, wOldMag-1, MF_BYPOSITION|MF_UNCHECKED );
if( (lpDisplay->wFlags & OIBF_ZOOMSELECT) &&
(lpDisplay->wScaleTo % lpDisplay->wScaleFrom) )
{
BYTE szMag[10];
WORD i,magnitude;
WORD wMag100 = (lpDisplay->wScaleTo*100)/lpDisplay->wScaleFrom;
wsprintf( (LPSTR)szMag, "%.3d:1", wMag100 );
magnitude = wMag100/100;
for( i=0; i<3 && magnitude; i++ )
{
szMag[i] = szMag[i+1];
magnitude /= 10;
}
szMag[i] = '.';
InsertMenu( hMagPopup, lpDisplay->wMagnification,
MF_BYPOSITION|MF_CHECKED|MF_STRING, OIBMENU_CUSTOMMAG, (LPSTR)szMag );
lpDisplay->wNumMagItems++;
}
else
CheckMenuItem( hMagPopup, lpDisplay->wMagnification-1, MF_BYPOSITION|MF_CHECKED );
}
#endif //SCCFEATURE_MENU
#endif
#ifdef SCCFEATURE_SCALING
/*
| Sets the scaling factor and mapping mode for subsequent operations.
*/
VOID OIBNPSetScaling( hdc, from, to )
HDC hdc;
WORD from;
WORD to;
{
SetMapMode( hdc, MM_ANISOTROPIC );
#ifdef WIN32
SetWindowExtEx( hdc, (LONG)from, (LONG)from, NULL );
SetViewportExtEx( hdc, (LONG)to, (LONG)to, NULL );
#else
SetWindowExt( hdc, from, from );
SetViewportExt( hdc, to, to );
#endif
}
/*
| Saves the current scaling values for later restoration.
*/
VOID OIBNPSaveScaling( hdc, lpDisplay )
DEVICE hdc;
POIB_DISPLAY lpDisplay;
{
lpDisplay->Mapping.oldMode = GetMapMode( hdc );
#ifdef WIN32
GetWindowExtEx(hdc,(LPSIZE)&lpDisplay->Mapping.oldWExt);
GetViewportExtEx(hdc,(LPSIZE)&lpDisplay->Mapping.oldVExt);
#else
*(LPDWORD)(&lpDisplay->Mapping.oldWExt) = GetWindowExt(hdc);
*(LPDWORD)(&lpDisplay->Mapping.oldVExt) = GetViewportExt(hdc);
#endif
}
/*
| Figure this one out yourself.
*/
VOID OIBNPRestoreScaling( hdc, lpDisplay )
DEVICE hdc;
POIB_DISPLAY lpDisplay;
{
SetMapMode( hdc, lpDisplay->Mapping.oldMode );
#ifdef WIN32
SetWindowExtEx( hdc, lpDisplay->Mapping.oldWExt.x, lpDisplay->Mapping.oldWExt.y, NULL );
SetViewportExtEx( hdc, lpDisplay->Mapping.oldVExt.x, lpDisplay->Mapping.oldVExt.y, NULL );
#else
SetWindowExt( hdc, lpDisplay->Mapping.oldWExt.x, lpDisplay->Mapping.oldWExt.y );
SetViewportExt( hdc, lpDisplay->Mapping.oldVExt.x, lpDisplay->Mapping.oldVExt.y );
#endif
}
/*
| This function reverses scaling on an array of points, using
| the current values of lpDisplay->wScaleFrom and lpDisplay->wScaleTo.
*/
VOID OIBNPReverseScale( hdc, Points, wCount, lpDisplay )
HDC hdc;
PSOPOINT Points;
WORD wCount;
POIB_DISPLAY lpDisplay;
{
if( hdc == NULL )
{
hdc = GetDC( lpDisplay->Gen.hWnd );
OIBNPSetScaling( hdc, lpDisplay->wScaleFrom, lpDisplay->wScaleTo );
BUDPtoLP( hdc, Points, wCount );
ReleaseDC( lpDisplay->Gen.hWnd, hdc );
}
else
BUDPtoLP( hdc, Points, wCount );
}
/*
| Scale an array of points.
*/
VOID OIBNPScale( hdc, Points, wCount, lpDisplay )
HDC hdc;
PSOPOINT Points;
WORD wCount;
POIB_DISPLAY lpDisplay;
{
if( hdc == NULL )
{
hdc = GetDC( lpDisplay->Gen.hWnd );
OIBNPSetScaling( hdc, lpDisplay->wScaleFrom, lpDisplay->wScaleTo );
BULPtoDP( hdc, Points, wCount );
ReleaseDC( lpDisplay->Gen.hWnd, hdc );
}
else
BULPtoDP( hdc, Points, wCount );
}
/*
| OIBNPFixScaledPoints
|
| Takes an array of points and "fixes" them so that they align
| to locations that can be produced through scaling. (...What?)
| Given a magnified image, where single pixels of the original
| image are now represented by squares several pixels wide, any
| random point in the magnified image gets mapped to the upper
| left corner of its magnified "pixel". This means the user
| can't select only a portion of a pixel, even when the image is
| magnified many times. Kind of hard to explain, but easy to see.
*/
VOID OIBNPFixScaledPoints( Points, lpDisplay, wCount )
PSOPOINT Points;
POIB_DISPLAY lpDisplay;
WORD wCount;
{
HDC hdc;
hdc = GetDC( lpDisplay->Gen.hWnd );
OIBNPSetScaling( hdc, lpDisplay->wScaleFrom, lpDisplay->wScaleTo );
BUDPtoLP( hdc, Points, wCount );
BULPtoDP( hdc, Points, wCount );
ReleaseDC( lpDisplay->Gen.hWnd, hdc );
}
#endif // SCCFEATURE_SCALING
/*
| Performs any necessary preparations for displaying an image.
| Currently not used.
*/
void OIBNPSetupBitmapDisplay(hdc,lpDisplay)
DEVICE hdc;
POIB_DISPLAY lpDisplay;
{
SetStretchBltMode( hdc, COLORONCOLOR );
}
/*
| Copies a tile's bitmap to the specified destination device.
*/
WORD OIBNPCopyBits( lpDisplay, pTile, dest, src, pSrcRect, pDestRect )
POIB_DISPLAY lpDisplay;
POIBTILE pTile;
DEVICE dest;
DEVICE src;
LPRECT pSrcRect; // Rectangle from source bitmap, in image coordinates
LPRECT pDestRect;
{
HANDLE hOldObject;
RECT destRect;
WORD wRet;
// HPALETTE hOldPal;
if( pDestRect == NULL )
{
if( pSrcRect == NULL )
return 0;
destRect = *pSrcRect;
}
else
destRect = *pDestRect;
/**
hOldPal = SelectPalette( dest, lpDisplay->Image.hPalette, FALSE );
RealizePalette( dest );
**/
hOldObject = SelectObject( src, pTile->hBmp );
wRet = StretchBlt( dest,
/* XDest */ destRect.left,
/* YDest */ destRect.top,
/* Width */ destRect.right - destRect.left,
/* Height*/ destRect.bottom - destRect.top,
src,
/* XSrc */ pSrcRect->left - pTile->Offset.x,
/* YSrc */ pSrcRect->top - pTile->Offset.y,
/* nSrcWidth */ pSrcRect->right - pSrcRect->left,
/* nSrcHeight */ pSrcRect->bottom - pSrcRect->top,
SRCCOPY );
SelectObject( src, hOldObject );
// SelectPalette( dest, hOldPal, TRUE );
return wRet;
}
#ifdef SCCFEATURE_FULLSCREEN
/*
| Performs any needed initialization in preparation for full screen display.
*/
WORD OIBNPInitFullScreen(lpDisplay)
POIB_DISPLAY lpDisplay;
{
HANDLE hDisplay;
OIBWRegisterFullScreenWndClass();
//hDisplay = GetWindowWord( lpDisplay->Gen.hWnd, SCCD_DATAHANDLE);
#ifdef WIN32
hDisplay = GlobalHandle(lpDisplay);
#else
hDisplay = (HANDLE) LOWORD(GlobalHandle(HIWORD((DWORD)lpDisplay)));
#endif
/*JKXXX
lpDisplay->hwndFullScreen =
CreateWindow( szFullScreenClassName,
NULL,
WS_POPUP | WS_VISIBLE,
0,
0,
lpDisplay->wScreenWidth,
lpDisplay->wScreenHeight,
lpDisplay->Gen.hWnd,
NULL,
hInst,
(LPSTR) &hDisplay );
*/
if( lpDisplay->hwndFullScreen != NULL )
return 0;
else
return 1;
}
/*
| Goes ahead and displays the image on the full screen.
*/
void OIBNPDisplayFullScreen( lpDisplay )
POIB_DISPLAY lpDisplay;
{
MSG Msg;
UpdateWindow( lpDisplay->hwndFullScreen );
SetFocus( lpDisplay->hwndFullScreen );
while (lpDisplay->wFlags & OIBF_FULLSCREEN)
{
if(PeekMessage(&Msg,0,0,0,PM_NOREMOVE))
{
GetMessage ( &Msg, 0, 0, 0 );
if ( (Msg.hwnd == lpDisplay->hwndFullScreen) ||
(Msg.message == WM_PAINT) ||
(Msg.message == WM_ERASEBKGND) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
if( !(lpDisplay->wFlags & OIBF_IMAGEPRESENT) )
{
DUReadMeAhead(lpDisplay);
// SendMessage(GetParent(lpDisplay->Gen.hWnd),SCCD_READMEAHEAD,0,0);
UpdateWindow( lpDisplay->hwndFullScreen );
}
}
}
VOID OIBNPDeInitFullScreen( lpDisplay )
POIB_DISPLAY lpDisplay;
{
if( lpDisplay->hwndFullScreen != NULL )
{
DestroyWindow(lpDisplay->hwndFullScreen);
lpDisplay->hwndFullScreen = NULL;
}
//JKXXX UnregisterClass( szFullScreenClassName, hInst );
SetFocus( lpDisplay->Gen.hWnd );
}
WIN_ENTRYSC LRESULT WIN_ENTRYMOD OIBWFullScreenWndProc( hwnd, message, wParam, lParam )
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
POIB_DISPLAY lpDisplay;
DWORD locRet = 0;
RECT rcUpdate;
HDC hdc;
PAINTSTRUCT ps;
HANDLE hDisplay;
if( message == WM_NCCREATE )
{
if ((locRet = DefWindowProc(hwnd, message, wParam, lParam)) != 0)
#ifdef WIN32
SetWindowLong( hwnd, 0, * (LONG VWPTR *) ((LPCREATESTRUCT)lParam)->lpCreateParams );
#else
SetWindowWord( hwnd, 0, * (WORD VWPTR *) ((LPCREATESTRUCT)lParam)->lpCreateParams );
#endif
return( locRet );
}
else
{
#ifdef WIN32
hDisplay = (HANDLE)GetWindowLong( hwnd, 0 );
#else
hDisplay = (HANDLE)GetWindowWord( hwnd, 0 );
#endif
lpDisplay = (POIB_DISPLAY) GlobalLock( hDisplay );
switch( message )
{
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
rcUpdate = ps.rcPaint;
#ifdef WIN32
SetViewportOrgEx( hdc,
lpDisplay->ptFullScreenOffset.x - lpDisplay->ptFullScreenShift.x,
lpDisplay->ptFullScreenOffset.y - lpDisplay->ptFullScreenShift.y, NULL );
#else
SetViewportOrg( hdc,
lpDisplay->ptFullScreenOffset.x - lpDisplay->ptFullScreenShift.x,
lpDisplay->ptFullScreenOffset.y - lpDisplay->ptFullScreenShift.y );
#endif
if( !(lpDisplay->wFlags & OIBF_IMAGEPRESENT) )
{
rcUpdate.left -= lpDisplay->ptFullScreenOffset.x;
rcUpdate.right -= lpDisplay->ptFullScreenOffset.x;
rcUpdate.top -= lpDisplay->ptFullScreenOffset.y;
rcUpdate.bottom -= lpDisplay->ptFullScreenOffset.y;
}
else
{
rcUpdate.left += lpDisplay->ptFullScreenShift.x - lpDisplay->ptFullScreenOffset.x;
rcUpdate.right += lpDisplay->ptFullScreenShift.x - lpDisplay->ptFullScreenOffset.x;
rcUpdate.top += lpDisplay->ptFullScreenShift.y - lpDisplay->ptFullScreenOffset.y;
rcUpdate.bottom += lpDisplay->ptFullScreenShift.y - lpDisplay->ptFullScreenOffset.y;
}
OIBDrawBitmap( hdc, &rcUpdate, lpDisplay );
EndPaint(hwnd, &ps);
break;
case WM_KEYDOWN:
{
SOPOINT ptScroll;
if( lpDisplay->wFlags & OIBF_IMAGEPRESENT )
{
ptScroll = lpDisplay->ptFullScreenShift;
switch( wParam )
{
case VK_PRIOR: // Page up.
if( !lpDisplay->ptFullScreenOffset.y )
{
ptScroll.y = max( 0, (SHORT)(lpDisplay->ptFullScreenShift.y -(SHORT)lpDisplay->wScreenHeight) );
}
break;
case VK_NEXT: // Page down.
if( !lpDisplay->ptFullScreenOffset.y )
{
ptScroll.y = min( lpDisplay->Image.DisplaySize.y - (SHORT)lpDisplay->wScreenHeight, (SHORT)(lpDisplay->ptFullScreenShift.y +(SHORT)lpDisplay->wScreenHeight) );
}
break;
case VK_UP:
if( !lpDisplay->ptFullScreenOffset.y )
{
ptScroll.y = max( 0, (SHORT)(lpDisplay->ptFullScreenShift.y - OIB_SCROLLINC) );
}
break;
case VK_DOWN:
if( !lpDisplay->ptFullScreenOffset.y )
{
ptScroll.y = min( lpDisplay->Image.DisplaySize.y - (SHORT)lpDisplay->wScreenHeight, (SHORT)(lpDisplay->ptFullScreenShift.y +OIB_SCROLLINC) );
}
break;
case VK_RIGHT:
if( !lpDisplay->ptFullScreenOffset.x )
{
ptScroll.x = min( lpDisplay->Image.DisplaySize.x - (SHORT)lpDisplay->wScreenWidth, (SHORT)(lpDisplay->ptFullScreenShift.x +OIB_SCROLLINC) );
}
break;
case VK_LEFT:
if( !lpDisplay->ptFullScreenOffset.x )
{
ptScroll.x = max( 0, (SHORT)(lpDisplay->ptFullScreenShift.x - OIB_SCROLLINC) );
}
break;
case VK_HOME:
ptScroll.x = 0;
ptScroll.y = 0;
break;
case VK_END:
if( !lpDisplay->ptFullScreenOffset.x )
ptScroll.x = lpDisplay->Image.DisplaySize.x - (SHORT)lpDisplay->wScreenWidth;
if( !lpDisplay->ptFullScreenOffset.y )
ptScroll.y = lpDisplay->Image.DisplaySize.y - (SHORT)lpDisplay->wScreenHeight;
break;
default:
lpDisplay->wFlags &= ~OIBF_FULLSCREEN;
// DestroyWindow(hwnd);
GlobalUnlock( hDisplay );
return 0;
}
if( ptScroll.x != lpDisplay->ptFullScreenShift.x ||
ptScroll.y != lpDisplay->ptFullScreenShift.y )
{
ScrollWindow( hwnd, lpDisplay->ptFullScreenShift.x-ptScroll.x, lpDisplay->ptFullScreenShift.y-ptScroll.y, NULL, NULL );
lpDisplay->ptFullScreenShift.x = ptScroll.x;
lpDisplay->ptFullScreenShift.y = ptScroll.y;
UpdateWindow( hwnd );
}
GlobalUnlock( hDisplay );
return 0;
}
else // Disable these keys when not available.
{
switch( wParam )
{
case VK_PRIOR: // Page up.
case VK_NEXT: // Page down.
case VK_UP:
case VK_DOWN:
case VK_RIGHT:
case VK_LEFT:
case VK_HOME:
case VK_END:
GlobalUnlock( hDisplay );
return 0;
}
}
}
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
lpDisplay->wFlags &= ~OIBF_FULLSCREEN;
// DestroyWindow(hwnd);
break;
default:
locRet = DefWindowProc(hwnd, message, wParam, lParam);
}
GlobalUnlock( hDisplay );
return( locRet );
}
}
VOID OIBWRegisterFullScreenWndClass()
{
/*JKXXX
WNDCLASS wc;
if( !GetClassInfo( hInst, (LPSTR)szFullScreenClassName, &wc ) )
{
wc.style = CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC) OIBWFullScreenWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof( HANDLE );
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = (LPSTR) NULL;
wc.lpszClassName = (LPSTR)szFullScreenClassName;
RegisterClass( &wc );
}
*/
}
#endif // SCCFEATURE_FULLSCREEN
/*
| Locks any platform-specific data structures needed for tile creation.
*/
VOID OIBNPLockBmInfo( lpDisplay )
POIB_DISPLAY lpDisplay;
{
lpDisplay->Image.Np.lpInfo = (LPBITMAPINFO) UTGlobalLock( lpDisplay->Image.Np.hDisplayBmpInfo );
lpDisplay->Image.Np.lpHead = (LPBITMAPINFOHEADER) lpDisplay->Image.Np.lpInfo;
}
/*
| Unlocks any platform-specific data structures needed for tile creation.
*/
VOID OIBNPUnlockBmInfo( lpDisplay )
POIB_DISPLAY lpDisplay;
{
UTGlobalUnlock( lpDisplay->Image.Np.hDisplayBmpInfo );
}
/*
| Uses the information in a chunk structure to set the size and offset
| values in a tile structure, and also sets any platform-specific
| size information needed for creating the tile's bitmap.
*/
VOID OIBNPSetTileDimensions( pTile, pChunk, lpDisplay )
POIBTILE pTile;
PCHUNK pChunk;
POIB_DISPLAY lpDisplay;
{
// Translate DIB coordinates to logical coordinates...
pTile->Offset.x = pChunk->Info.Bitmap.wXOffset;
pTile->Offset.y = lpDisplay->Image.wOrgHeight - pChunk->Info.Bitmap.wYOffset - pChunk->Info.Bitmap.wYClip;
pTile->Size.x = pChunk->Info.Bitmap.wXClip;
pTile->Size.y = pChunk->Info.Bitmap.wYClip;
#ifdef SCCFEATURE_ROTATION
if( lpDisplay->wRotation & OIB_ROTATE90 )
OIBNPRotateTileDimensions( lpDisplay, pTile );
if( lpDisplay->wRotation & OIB_ROTATE180 )
{
pTile->Offset.x = lpDisplay->Image.wWidth - pTile->Offset.x - pTile->Size.x;
pTile->Offset.y = lpDisplay->Image.wHeight - pTile->Offset.y - pTile->Size.y;
}
#endif
}
/*
| Uses the data from a chunk to create a tile's bitmap.
*/
HBITMAP OIBNPSetTileBits( pTile, wTile, hdc, lpDisplay )
POIBTILE pTile;
WORD wTile;
DEVICE hdc;
POIB_DISPLAY lpDisplay;
{
LPSTR pChunkData;
HANDLE hChunkData;
hChunkData = CHTakeChunk( lpDisplay->Gen.wSection, wTile, lpDisplay->Gen.hFilter );
lpDisplay->Image.Np.lpHead->biWidth = (DWORD) pTile->Size.x;
lpDisplay->Image.Np.lpHead->biHeight = (DWORD) pTile->Size.y;
if( lpDisplay->wFlags & OIBF_TRUECOLORTO256 )
{
pChunkData = (LPSTR) UTGlobalLock( hChunkData );
#ifdef SCCFEATURE_DITHER
if( lpDisplay->bDither )
OIBWDither8Bit( hdc, pChunkData, lpDisplay, pTile );
else
#endif
OIBWMapTrueColorBitmap( hdc, pChunkData, lpDisplay, pTile );
UTGlobalUnlock( hChunkData );
UTGlobalFree( hChunkData );
}
#ifdef SCCFEATURE_DITHER
else if( lpDisplay->wFlags & OIBF_DITHER4BIT && lpDisplay->bDither )
{
pChunkData = (LPSTR) UTGlobalLock( hChunkData );
OIBWDither4Bit( hdc, pChunkData, lpDisplay, pTile );
UTGlobalUnlock( hChunkData );
UTGlobalFree( hChunkData );
}
#endif
else
{
#ifdef SCCFEATURE_ROTATION
if( lpDisplay->wRotation & OIB_ROTATE90 )
{
// This covers the 270 degree rotation, too.
// (We'll rotate it the remaining 180 degrees below. Don't worry.)
OIBCreateRotatedBmp( lpDisplay, hdc, pTile, hChunkData );
}
else
#endif
OIBNPCreateTileBitmap( lpDisplay, hdc, pTile, hChunkData );
}
#ifdef SCCFEATURE_ROTATION
if( (lpDisplay->wRotation & OIB_ROTATE180) && pTile->hBmp != NULL )
OIBNPRotateTile180( lpDisplay, pTile, hdc );
#endif
return( pTile->hBmp );
}
/*
| Performs platform-specific calls to set a tile's bitmap bits.
| This function is responsible for freeing bitmap memory that
| is no longer needed.
*/
void OIBNPCreateTileBitmap( lpDisplay, hdc, pTile, hBits )
POIB_DISPLAY lpDisplay;
DEVICE hdc;
POIBTILE pTile;
HANDLE hBits;
{
LPSTR pBits = UTGlobalLock( hBits );
if( lpDisplay->Image.wBitCount == 1 )
{
pTile->hBmp = CreateBitmap( (WORD)pTile->Size.x, (WORD)pTile->Size.y, 1, 1, NULL );
if( pTile->hBmp != NULL )
SetDIBits( hdc, pTile->hBmp, 0, (WORD)pTile->Size.y, pBits, lpDisplay->Image.Np.lpInfo, lpDisplay->Image.wCreateBmpFlags );
}
else
pTile->hBmp = CreateDIBitmap( hdc, lpDisplay->Image.Np.lpHead, CBM_INIT, pBits, lpDisplay->Image.Np.lpInfo, lpDisplay->Image.wCreateBmpFlags );
UTGlobalUnlock( hBits );
UTGlobalFree( hBits );
}
#ifdef SCCFEATURE_ROTATION
HANDLE OIBNPRotateChunk( hChunkData, lpTile, lpDisplay )
HANDLE hChunkData;
POIBTILE lpTile;
POIB_DISPLAY lpDisplay;
{
HANDLE hNewData = NULL;
LPSTR pChunkData;
LPSTR pNewData;
WORD wNewLineSize;
WORD wBitCount;
wBitCount = lpDisplay->Image.wBitCount;
// Check for color reduction, because this function
// is called after color reduction operations.
if( lpDisplay->wFlags & OIBF_TRUECOLORTO256 )
wBitCount = 8;
#ifdef SCCFEATURE_DITHER
else if( Options.bDither )
{
if( lpDisplay->wScreenColors == 256 )
wBitCount = 8;
else if( lpDisplay->wScreenColors == 16 )
wBitCount = 4;
}
#endif
// Note that before this function is called, the x and y values have been
// swapped to reflect their post-rotation values.
wNewLineSize = OIBScanLineSize(lpTile->Size.x,wBitCount,NULL);
hNewData = UTGlobalAlloc(wNewLineSize * lpTile->Size.y);
if( hNewData != NULL )
{
pNewData = UTGlobalLock( hNewData );
pChunkData = UTGlobalLock( hChunkData );
OIBRotateDIBits( pChunkData, pNewData, lpTile->Size.y, lpTile->Size.x, wBitCount );
UTGlobalUnlock( hNewData );
}
UTGlobalUnlock( hChunkData );
UTGlobalFree( hChunkData );
return hNewData;
}
/*
| Changes the values in a tile structure to reflect 90 or 270 degree
| rotation of the tile, and sets up any platform-specific data
| structures to prepare for creating a rotated bitmap for the tile.
*/
VOID OIBNPRotateTileDimensions( lpDisplay, lpTile )
POIB_DISPLAY lpDisplay;
POIBTILE lpTile;
{
SHORT temp;
temp = lpTile->Offset.x;
lpTile->Offset.x = lpDisplay->Image.wOrgHeight - (lpTile->Offset.y + lpTile->Size.y);
lpTile->Offset.y = temp;
temp = lpTile->Size.x;
lpTile->Size.x = lpTile->Size.y;
lpTile->Size.y = temp;
}
/*
| Takes a tile with an existing bitmap and rotates it 180 degrees,
| reflecting the rotation in the tile's offset values as well as
| the bitmap itself.
*/
VOID OIBNPRotateTile180( lpDisplay, lpTile, hdc )
POIB_DISPLAY lpDisplay;
POIBTILE lpTile;
DEVICE hdc;
{
HANDLE hOldBmp;
SHORT nDestWidth;
SHORT nDestHeight;
DEVICE hdc2;
nDestWidth = 0 - lpTile->Size.x;
nDestHeight = 0 - lpTile->Size.y;
hdc2 = CreateCompatibleDC( hdc );
OIBNPSetPalette( hdc2, lpDisplay );
hOldBmp = SelectObject( hdc2, lpTile->hBmp );
// We'll use StretchBlt to flip the bitmap:
if( lpDisplay->Image.wBitCount != 1 )
{
StretchBlt( hdc2,
lpTile->Size.x-1, lpTile->Size.y-1,
nDestWidth, nDestHeight,
hdc2,
0, 0,
lpTile->Size.x, lpTile->Size.y,
SRCCOPY);
}
else
{
// Work-around for a bug in Windows:
// StretchBlt chokes when trying to flip a monochrome bitmap
// whose width doesn't end on a byte boundary, so
// we'll pretend the width DOES end on a byte boundary.
SHORT excess = lpTile->Size.x % 8;
if( excess )
excess = 8-excess;
StretchBlt( hdc2,
lpTile->Size.x + excess -1, lpTile->Size.y-1,
nDestWidth - excess, nDestHeight,
hdc2,
0 - excess, 0,
lpTile->Size.x + excess, lpTile->Size.y,
SRCCOPY);
}
SelectObject( hdc2, hOldBmp );
BUDeleteDevice( hdc2 );
}
#endif //SCCFEATURE_ROTATION
#ifdef SCCFEATURE_CLIP
VOID OIBNPGetRenderInfo( lpDisplay, pRender, wFormat )
POIB_DISPLAY lpDisplay;
PSCCDRENDERINFO pRender;
WORD wFormat;
{
BYTE locStr[100];
pRender->wSubFormatId = 0;
pRender->szSubFormatName[0] = 0;
/*JKXXX
switch( wFormat )
{
case 0:
pRender->wFormatId = SCCD_FORMAT_WINBITMAP;
LoadString( hInst, OIBSTR_RENDERWINBMP, locStr, 100 );
break;
case 1:
pRender->wFormatId = SCCD_FORMAT_WINDIB;
LoadString( hInst, OIBSTR_RENDERWINDIB, locStr, 100 );
break;
case 2:
pRender->wFormatId = SCCD_FORMAT_WINPALETTE;
LoadString( hInst, OIBSTR_RENDERWINPAL, locStr, 100 );
break;
}
*/
UTstrcpy( (LPSTR) pRender->szFormatName, locStr );
}
DWORD OIBNPRenderData( lpDisplay, pData, wRenderFlag )
POIB_DISPLAY lpDisplay;
PSCCDRENDERDATA pData;
WORD wRenderFlag;
{
BOOL ret;
pData->hData = NULL;
pData->dwDataSize = 0;
switch( pData->wFormatId )
{
case SCCD_FORMAT_WINBITMAP:
if( wRenderFlag || (Options.wClipFormats & OIB_CLIPBITMAP) )
ret = (BOOL) OIBNPRenderBmp(lpDisplay, pData);
break;
case SCCD_FORMAT_WINDIB:
if( wRenderFlag || (Options.wClipFormats & OIB_CLIPDIB) )
ret = (BOOL) OIBNPRenderDIB(lpDisplay, pData );
break;
case SCCD_FORMAT_WINPALETTE:
if( wRenderFlag || (Options.wClipFormats & OIB_CLIPPALETTE) )
ret = (BOOL) OIBNPRenderPalette(lpDisplay, pData );
break;
}
return (DWORD) ret;
}
DWORD OIBNPRenderBmp( lpDisplay, pData )
POIB_DISPLAY lpDisplay;
PSCCDRENDERDATA pData;
{
HDC hWndDC;
HDC hdc;
// BITMAP bm;
HBITMAP hOldBitmap;
HBITMAP hBmpClip = NULL;
LPBITMAPINFO lpInfo;
LPBITMAPINFOHEADER lpHead;
lpInfo = (LPBITMAPINFO) GlobalLock( lpDisplay->Image.Np.hDocBmpInfo );
lpHead = (LPBITMAPINFOHEADER) lpInfo;
hWndDC = GetDC( lpDisplay->Gen.hWnd );
OIBNPSetPalette(hWndDC, lpDisplay );
hdc = CreateCompatibleDC( hWndDC );
OIBNPSetPalette(hdc, lpDisplay );
lpHead->biWidth = (DWORD) (lpDisplay->rcSelect.right - lpDisplay->rcSelect.left );
lpHead->biHeight = (DWORD) (lpDisplay->rcSelect.bottom - lpDisplay->rcSelect.top );
hBmpClip = CreateCompatibleBitmap( hWndDC, (SHORT)lpHead->biWidth, (SHORT)lpHead->biHeight );
if( hBmpClip != NULL )
{
#ifdef WIN32
SetWindowOrgEx( hdc, lpDisplay->rcSelect.left, lpDisplay->rcSelect.top, NULL );
#else
SetWindowOrg( hdc, lpDisplay->rcSelect.left, lpDisplay->rcSelect.top );
#endif
hOldBitmap = SelectObject( hdc, hBmpClip );
OIBDrawBitmap( hdc, &(lpDisplay->rcSelect), lpDisplay );
// GetObject(hBmpClip,sizeof(BITMAP),&bm);
BUSetWindowOrg( hdc, 0, 0 );
SelectObject( hdc, hOldBitmap );
pData->dwDataSize = sizeof(BITMAP); // actually, any non-zero value will work.
}
else
pData->dwDataSize = 0;
pData->hData = hBmpClip;
DeleteDC( hdc );
ReleaseDC( lpDisplay->Gen.hWnd, hWndDC );
return pData->dwDataSize;
}
DWORD OIBNPRenderDIB( lpDisplay, pData )
POIB_DISPLAY lpDisplay;
PSCCDRENDERDATA pData;
{
HDC hWndDC;
HDC hdc;
LPBITMAPINFO lpInfo;
LPBITMAPINFOHEADER lpHead;
HANDLE hDIBClip = NULL;
DWORD dwDibSize;
LPSTR lpDib;
lpInfo = (LPBITMAPINFO) GlobalLock( lpDisplay->Image.Np.hDocBmpInfo );
lpHead = (LPBITMAPINFOHEADER) lpInfo;
hWndDC = GetDC( lpDisplay->Gen.hWnd );
OIBNPSetPalette(hWndDC, lpDisplay );
hdc = CreateCompatibleDC( hWndDC );
OIBNPSetPalette(hdc, lpDisplay );
lpHead->biWidth = (DWORD) (lpDisplay->rcSelect.right - lpDisplay->rcSelect.left );
lpHead->biHeight = (DWORD) (lpDisplay->rcSelect.bottom - lpDisplay->rcSelect.top );
if( lpDisplay->Image.wBitCount != 1 )
hDIBClip = OIBNPGetDIBRect( hdc, lpHead, lpDisplay, (LPDWORD)&pData->dwDataSize );
else
{
OIBNPRenderBmp( lpDisplay, pData );
if( pData->hData == NULL )
return 0; // FAILURE.
// Set dwDibSize to the size of one scan line...
dwDibSize = (DWORD) OIBScanLineSize( (WORD)lpHead->biWidth, 1, NULL );
// ...multiply by the number of lines...
dwDibSize *= lpHead->biHeight;
// ...and add the size of the Info structure.
dwDibSize += (WORD)lpHead->biSize + sizeof(RGBQUAD) * 2;
hDIBClip = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, dwDibSize );
if( hDIBClip != NULL )
{
lpDib = GlobalLock( hDIBClip );
UTmemcpy( lpDib, lpInfo, (WORD)lpHead->biSize+sizeof(RGBQUAD)*2 );
lpDib += lpHead->biSize + sizeof(RGBQUAD) * 2;
GetDIBits( hdc, pData->hData, 0, (WORD)lpHead->biHeight, lpDib, lpInfo, DIB_RGB_COLORS );
}
DeleteObject( pData->hData );
pData->dwDataSize = dwDibSize;
}
pData->hData = hDIBClip;
DeleteDC( hdc );
ReleaseDC( lpDisplay->Gen.hWnd, hWndDC );
return pData->dwDataSize;
}
DWORD OIBNPRenderPalette( lpDisplay, pData )
POIB_DISPLAY lpDisplay;
PSCCDRENDERDATA pData;
{
LPLOGPALETTE lpPalette;
HANDLE hPaletteMem = NULL;
HPALETTE hPalette = NULL;
DWORD dwPalSize = 0;
if( lpDisplay->Image.hPalette != NULL )
{
dwPalSize = sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * lpDisplay->Image.wPaletteSize;
hPaletteMem = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE, dwPalSize );
if( hPaletteMem != NULL )
{
lpPalette = (LPLOGPALETTE) GlobalLock(hPaletteMem);
lpPalette->palVersion = 0x0300;
lpPalette->palNumEntries = lpDisplay->Image.wPaletteSize;
GetPaletteEntries( lpDisplay->Image.hPalette, 0, lpDisplay->Image.wPaletteSize, (LPPALETTEENTRY) &(lpPalette->palPalEntry) );
hPalette = CreatePalette( lpPalette );
GlobalUnlock( hPaletteMem );
GlobalFree( hPaletteMem );
}
}
pData->dwDataSize = dwPalSize;
pData->hData = hPalette;
return dwPalSize;
}
/*
| Fills a rectangle with the original device independent bits from
| the filter.
*/
HANDLE OIBNPGetDIBRect( hdc, lpHead, lpDisplay, pDataSize )
HDC hdc;
LPBITMAPINFOHEADER lpHead;
POIB_DISPLAY lpDisplay;
LPDWORD pDataSize;
{
WORD wInfoSize;
DWORD dwBitmapSize;
DWORD dwDib2Size;
WORD wScanLineSize;
WORD wScanLineDataSize;
WORD wNumColors = 0;
HANDLE hDib, hDib2;
LPSTR lpDib, lpDib2;
RECT locRect;
locRect = lpDisplay->rcSelect;
#ifdef SCCFEATURE_ROTATION
// First, we'll fix up the rectangle to account for rotation, and then
// fix up the rectangle to reflect the DIB bottom-to-top storage.
if( lpDisplay->wRotation != OIB_NOROTATION )
{
OIBUnrotateRect( lpDisplay, &(locRect) );
}
if( lpDisplay->wRotation & OIB_ROTATE90 )
{
// Width is height, height is width. (Ooo... cosmic.)
locRect.top = lpDisplay->Image.DisplaySize.x - locRect.top;
locRect.bottom = lpDisplay->Image.DisplaySize.x - locRect.bottom;
}
else
#endif //SCCFEATURE_ROTATION
{
locRect.top = lpDisplay->Image.DisplaySize.y - locRect.top;
locRect.bottom = lpDisplay->Image.DisplaySize.y - locRect.bottom;
}
if( lpDisplay->Image.wBitCount == 24 )
wInfoSize = (WORD)lpHead->biSize;
else
{
wNumColors = (WORD)lpHead->biClrUsed;
if( !wNumColors )
wNumColors = 1 << lpDisplay->Image.wBitCount;
wInfoSize = (WORD)lpHead->biSize + sizeof(RGBQUAD) * wNumColors;
}
wScanLineSize = OIBScanLineSize( (WORD)(locRect.right-locRect.left), lpDisplay->Image.wBitCount, (LPWORD)&wScanLineDataSize );
dwBitmapSize = (DWORD)wScanLineSize * (locRect.top-locRect.bottom);
hDib = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, dwBitmapSize + wInfoSize );
if( hDib != NULL )
{
lpDib = (LPSTR) GlobalLock( hDib );
UTmemcpy( lpDib, (LPSTR) lpHead, wInfoSize );
if( lpDisplay->wFlags & OIBF_SELECTALL &&
!(lpDisplay->wRotation & OIB_ROTATE90) ) // 90 degree rotation requires so much processing that this optimized routine won't help.
{
OIBNPCopyImageDIB( lpDisplay, (HPBYTE) &(lpDib[wInfoSize]), wScanLineSize );
}
else
{
OIBNPSetClipBits( lpDisplay, (HPBYTE) &(lpDib[wInfoSize]), (RECT VWPTR *)&locRect, wScanLineSize, wScanLineDataSize, lpDisplay->Image.wBitCount );
#ifdef SCCFEATURE_ROTATION
if( lpDisplay->wRotation & OIB_ROTATE90 )
{
// Well now, this is a whole new ball game:
// We have to rotate the unrotated DIB. Let's allocate
// a new one, shall we? NOTE: the width and height
// fields in lpHead have been set by the calling function,
// and reflect the ROTATED dimensions of the rectangle.
wScanLineSize = OIBScanLineSize( (WORD) lpHead->biWidth, lpDisplay->Image.wBitCount, 0 );
dwDib2Size = (DWORD)wScanLineSize * lpHead->biHeight + wInfoSize;
hDib2 = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, dwDib2Size );
if( hDib2 == NULL )
{
GlobalUnlock( hDib );
GlobalFree( hDib );
return NULL;
}
else
{
lpDib2 = GlobalLock( hDib2 );
UTmemcpy( lpDib2, (LPSTR) lpHead, wInfoSize );
OIBRotateDIBits( (HPBYTE) &(lpDib[wInfoSize]), (HPBYTE) &(lpDib2[wInfoSize]),
(WORD)lpHead->biHeight, (WORD)lpHead->biWidth, lpDisplay->Image.wBitCount );
GlobalUnlock( hDib );
GlobalFree( hDib );
hDib = hDib2;
lpDib = lpDib2;
}
}
if( lpDisplay->wRotation & OIB_ROTATE180 )
OIBRotateDIBits180( (HPBYTE) &(lpDib[wInfoSize]), wScanLineSize, (WORD)lpHead->biWidth, (WORD)lpHead->biHeight, lpDisplay->Image.wBitCount );
#endif
}
GlobalUnlock( hDib );
}
if( pDataSize != NULL )
*pDataSize = dwBitmapSize + wInfoSize;
return( hDib );
}
VOID OIBNPSetClipBits( lpDisplay, lpBits, lpRect, wLineSize, wLineDataSize, wBitCount )
POIB_DISPLAY lpDisplay;
HPBYTE lpBits;
RECT VWPTR * lpRect;
WORD wLineSize;
WORD wLineDataSize;
WORD wBitCount;
{
WORD wBitShift = 0;
WORD wCurLine;
CHSECTIONINFO SecInfo;
PCHUNK pChunkTable;
HANDLE hData;
HPBYTE lpData;
WORD wScanLineOffset;
WORD wCurChunk;
WORD wLimitLine;
WORD wChunkLineSize;
WORD wPixPerByte;
WORD wPixPerLine;
// See if we have to shift the bytes from the original data
// to align correctly in our new bitmap.
wPixPerByte = 8 / wBitCount;
if( wBitCount < 8 )
{
if( lpRect->left < (SHORT) wPixPerByte )
wBitShift = lpRect->left * wBitCount;
else
wBitShift = (lpRect->left % wPixPerByte) * wBitCount;
}
// CHGetSecInfo( lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection, &SecInfo );
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
pChunkTable = (PCHUNK) GlobalLock( SecInfo.hChunkTable );
wCurLine = (WORD)lpRect->bottom;
wCurChunk = 0;
while( (SHORT) wCurLine < lpRect->top )
{
while( !(pChunkTable[wCurChunk].Info.Bitmap.wYOffset <= wCurLine &&
pChunkTable[wCurChunk].Info.Bitmap.wYOffset+pChunkTable[wCurChunk].Info.Bitmap.wYClip > wCurLine) )
{
wCurChunk++;
if( wCurChunk == SecInfo.wCurTotalChunks )
{
// Don't make any assumptions about chunk ordering.
wCurChunk = 0;
}
}
// We'll have to deal with horizontal tiling, too!
hData = CHGetChunk( lpDisplay->Gen.wSection, wCurChunk, lpDisplay->Gen.hFilter );
lpData = (HPBYTE) GlobalLock( hData );
if( wPixPerByte )
wScanLineOffset = lpRect->left / wPixPerByte;
else // 24-bit
wScanLineOffset = lpRect->left * 3;
wLimitLine = min( (WORD)lpRect->top, pChunkTable[wCurChunk].Info.Bitmap.wYOffset+pChunkTable[wCurChunk].Info.Bitmap.wYClip );
wPixPerLine = (WORD)(lpRect->right - lpRect->left);
wChunkLineSize = (WORD)pChunkTable[0].dwSize / pChunkTable[0].Info.Bitmap.wLength;
lpData += (DWORD)((DWORD)wScanLineOffset + (DWORD)wChunkLineSize * ((DWORD)wCurLine - pChunkTable[wCurChunk].Info.Bitmap.wYOffset));
while( wCurLine < wLimitLine )
{
if( wBitShift )
OIBBitShiftCopy( (HPBYTE)lpBits, lpData, wBitShift, wLineDataSize, wPixPerLine, wPixPerByte );
else
{
UTmemcpy( lpBits, lpData, wLineDataSize );
}
wCurLine++;
lpBits += wLineSize;
lpData += wChunkLineSize;
}
GlobalUnlock( hData );
}
GlobalUnlock( SecInfo.hChunkTable );
}
VOID OIBNPCopyImageDIB( lpDisplay, lpBits, wLineSize )
POIB_DISPLAY lpDisplay;
HPBYTE lpBits;
WORD wLineSize;
{
WORD wCurLine;
CHSECTIONINFO SecInfo;
PCHUNK pChunkTable;
HANDLE hData;
HPBYTE lpData;
WORD wCurChunk;
WORD i;
WORD wNumLines;
WORD wWidth;
HPBYTE lpDest = lpBits;
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
pChunkTable = (PCHUNK) GlobalLock( SecInfo.hChunkTable );
wCurLine = 0;
wCurChunk = 0;
for( i=0; i<= SecInfo.IDLastChunk; i++ )
{
while( !(pChunkTable[wCurChunk].Info.Bitmap.wYOffset <= wCurLine &&
pChunkTable[wCurChunk].Info.Bitmap.wYOffset+pChunkTable[wCurChunk].Info.Bitmap.wYClip > wCurLine) )
{
wCurChunk++;
if( wCurChunk == SecInfo.wCurTotalChunks )
{
// Don't make any assumptions about chunk ordering.
wCurChunk = 0;
}
}
// We'll have to deal with horizontal tiling, too! (Yeah, right.)
hData = CHGetChunk( lpDisplay->Gen.wSection, wCurChunk, lpDisplay->Gen.hFilter );
lpData = (HPBYTE) GlobalLock( hData );
wNumLines = pChunkTable[wCurChunk].Info.Bitmap.wYClip;
wWidth = pChunkTable[wCurChunk].Info.Bitmap.wXClip;
UTmemcpy( lpDest, lpData, (WORD)(wNumLines * wLineSize) );
lpDest += (DWORD)((DWORD)wNumLines * (DWORD)wLineSize);
wCurLine += pChunkTable[wCurChunk].Info.Bitmap.wYClip;
GlobalUnlock( hData );
}
#ifdef SCCFEATURE_ROTATION
if( lpDisplay->wRotation & OIB_ROTATE180 )
OIBRotateDIBits180( lpBits, wLineSize, wWidth, SecInfo.Attr.Bitmap.bmpHeader.wImageLength, lpDisplay->Image.wBitCount );
#endif
GlobalUnlock( SecInfo.hChunkTable );
}
#endif // SCCFEATURE_CLIP
#ifdef SCCFEATURE_DRAWTORECT
DWORD OIBNPInitDrawToRect(pDraw, lpDisplay)
PSCCDDRAWTORECT pDraw;
POIB_DISPLAY lpDisplay;
{
LPRECT pImageRect = (LPRECT)(pDraw->pPosition);
// This positioning rectangle is redundant.
if( pDraw->bLoadDoc )
{
OIBInitBitmapDisplay( lpDisplay, OIBF_RENDERIMAGEONLY );
}
if( pDraw->bWholeDoc || !lpDisplay->bSelectionMade || pDraw->bLoadDoc )
{
pImageRect->top = 0;
pImageRect->left = 0;
pImageRect->right = lpDisplay->Image.wWidth;
pImageRect->bottom = lpDisplay->Image.wHeight;
}
else
*pImageRect = lpDisplay->rcSelect;
#ifdef SCCFEATURE_ROTATION
// Fix up the rectangle to account for rotation:
if( lpDisplay->wRotation != OIB_NOROTATION )
OIBUnrotateRect( lpDisplay, pImageRect );
#endif
return TRUE;
}
DWORD OIBNPMapDrawToRect(pDraw, lpDisplay)
PSCCDDRAWTORECT pDraw;
POIB_DISPLAY lpDisplay;
{
LPRECT pImageRect = (LPRECT)(pDraw->pPosition);
pDraw->lDELeft = (LONG)pImageRect->left;
pDraw->lDETop = (LONG)pImageRect->top;
pDraw->lDERight = (LONG)pImageRect->right;
pDraw->lDEBottom = (LONG)pImageRect->bottom;
return 0;
}
LONG OIBNPDrawToRect( pDraw, lpDisplay )
PSCCDDRAWTORECT pDraw;
POIB_DISPLAY lpDisplay;
{
LPRECT pImageRect = (LPRECT)(pDraw->pPosition);
DEVICE hdc;
CHSECTIONINFO SecInfo;
RECT Intersect;
RECT pageRect, chunkRect;
PCHUNK pChunkTable;
HANDLE hChunkData;
LPSTR pChunkData;
SHORT i;
DWORD dwLinesToRender;
HPALETTE hOldPal;
LPBITMAPINFO locBitmapInfo;
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
SetRect( &pageRect, (SHORT)pDraw->lLeft, (SHORT)pDraw->lTop, (SHORT)pDraw->lRight, (SHORT)pDraw->lBottom );
hdc = lpDisplay->Gen.hDC;
hOldPal = lpDisplay->Image.hPalette;
// OIBNPInitPalette( lpDisplay, NULL );
OIBNPSetPalette( hdc, lpDisplay );
//pDraw->hPalette = lpDisplay->Image.hPalette;
pDraw->hPalette = NULL;
// Note that for this routine we have to lock the hDocBmpInfo handle, which is guaranteed
// to refer to an explicit RGB palette. This is because we're using StretchDIBits instead
// of StretchBlt. (The hDisplayBmpInfo handle usually refers to an indexed palette.)
locBitmapInfo = (LPBITMAPINFO) GlobalLock( lpDisplay->Image.Np.hDocBmpInfo );
i = 0;
SetStretchBltMode( hdc, COLORONCOLOR );
dwLinesToRender = pImageRect->bottom - pImageRect->top;
while( i != (SHORT)SecInfo.wChunkTableSize && dwLinesToRender )
{
if( pDraw->bLoadDoc || SecInfo.wCurTotalChunks < (WORD)i+1 )
{
DUReadMeAhead(lpDisplay);
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
}
pChunkTable = (PCHUNK) UTGlobalLock( SecInfo.hChunkTable );
// Fix up the DIB bottom-to-top stuff for the Y direction.
chunkRect.top = SecInfo.Attr.Bitmap.bmpHeader.wImageLength - (pChunkTable[i].Info.Bitmap.wYOffset +pChunkTable[i].Info.Bitmap.wYClip);
chunkRect.bottom = chunkRect.top + pChunkTable[i].Info.Bitmap.wYClip;
chunkRect.left = pChunkTable[i].Info.Bitmap.wXOffset;
chunkRect.right = chunkRect.left + pChunkTable[i].Info.Bitmap.wXClip;
if( BUIntersectRect(&Intersect, pImageRect, &chunkRect) )
{
hChunkData = CHGetChunk( lpDisplay->Gen.wSection, i, lpDisplay->Gen.hFilter );
pChunkData = (LPSTR) UTGlobalLock( hChunkData );
locBitmapInfo->bmiHeader.biWidth = (DWORD) pChunkTable[i].Info.Bitmap.wXClip;
locBitmapInfo->bmiHeader.biHeight = (DWORD) pChunkTable[i].Info.Bitmap.wYClip;
if( 0 == StretchDIBits( hdc,
/* DestX */ Intersect.left,
/* DestY */ Intersect.top,
/* DestWidth */ Intersect.right-Intersect.left,
/* DestHeight */ Intersect.bottom-Intersect.top,
/* SrcX */ Intersect.left - chunkRect.left,
/* SrcY */ chunkRect.bottom - Intersect.bottom,
/* SrcWidth */ Intersect.right-Intersect.left,
/* SrcHeight */ Intersect.bottom-Intersect.top,
/* lpBits */ pChunkData,
/* lpBitsInfo */ locBitmapInfo,
/* wUsage */ DIB_RGB_COLORS,
/* dwRop */ SRCCOPY ) )
{
dwLinesToRender = 0; // Break out.
}
else
dwLinesToRender -= Intersect.bottom - Intersect.top;
UTGlobalUnlock( hChunkData );
}
UTGlobalUnlock( SecInfo.hChunkTable );
i++;
}
lpDisplay->Image.hPalette = hOldPal;
UTGlobalUnlock( lpDisplay->Image.Np.hDocBmpInfo );
if( lpDisplay->wFlags & OIBF_RENDERIMAGEONLY )
OIBDeInitDisplay(lpDisplay);
return 0;
}
#endif //SCCFEATURE_DRAWTORECT
/*
| Makes the image's palette the current palette for subsequent
| bit operations.
*/
HPALETTE OIBNPSetPalette(hdc, lpDisplay )
HDC hdc;
POIB_DISPLAY lpDisplay;
{
HPALETTE hOldPal = NULL;
if( lpDisplay->Image.hPalette != NULL )
{
hOldPal = SelectPalette( hdc, lpDisplay->Image.hPalette, FALSE );
RealizePalette( hdc );
}
return( hOldPal );
}
/*
| Frees any memory allocation for palettes.
*/
VOID OIBNPFreePalette(lpDisplay)
POIB_DISPLAY lpDisplay;
{
if( lpDisplay->Image.hPalette != NULL )
{
DeleteObject( lpDisplay->Image.hPalette );
lpDisplay->Image.hPalette = NULL;
}
if( lpDisplay->hPalMem != NULL )
{
LocalFree(lpDisplay->hPalMem);
lpDisplay->hPalMem = NULL;
}
}
/*
| Frees the allocated tile structures.
*/
VOID OIBNPFreeImageTiles( lpDisplay )
POIB_DISPLAY lpDisplay;
{
WORD i;
for( i=0; i< lpDisplay->Image.wNumTiles; i++ )
{
if( lpDisplay->Image.pBmpTiles[i].hBmp != NULL )
DeleteObject( lpDisplay->Image.pBmpTiles[i].hBmp );
}
GlobalUnlock( lpDisplay->Image.hTiles );
GlobalFree( lpDisplay->Image.hTiles );
lpDisplay->Image.hTiles = NULL;
lpDisplay->Image.wNumTiles = 0;
lpDisplay->Image.pBmpTiles = NULL;
lpDisplay->Image.TileCache.wCount = 0;
lpDisplay->Image.TileCache.bCacheFull = FALSE;
}
#ifdef SCCFEATURE_ROTATION
/*
| Handles the rotation menu selection, unchecking the previous
| selection and checking the new one. Returns TRUE if the rotation
| choice has actually changed, FALSE otherwise.
*/
BOOL OIBNPChooseRotation( lpDisplay, wRotation, hMenu, wMenuItem )
POIB_DISPLAY lpDisplay;
WORD wRotation;
HANDLE hMenu;
WORD wMenuItem;
{
WORD wOldItem;
if( lpDisplay->wRotation == wRotation )
return FALSE;
// Handle the menu stuff...
switch( lpDisplay->wRotation )
{
case OIB_NOROTATION:
wOldItem = OIBMENU_NOROTATION;
break;
case OIB_ROTATE90:
wOldItem = OIBMENU_ROTATE90;
break;
case OIB_ROTATE180:
wOldItem = OIBMENU_ROTATE180;
break;
case OIB_ROTATE270:
wOldItem = OIBMENU_ROTATE270;
break;
}
#ifdef SCCFEATURE_MENU
CheckMenuItem( hMenu, lpDisplay->Gen.wMenuOffset + wOldItem, MF_BYCOMMAND|MF_UNCHECKED );
CheckMenuItem( hMenu, lpDisplay->Gen.wMenuOffset + wMenuItem, MF_BYCOMMAND|MF_CHECKED );
#endif //SCCFEATURE_MENU
return TRUE;
}
#endif //SCCFEATURE_ROTATION
#ifdef SCCFEATURE_SELECT
VOID OIBNPDrawSelectBox(lpDisplay)
POIB_DISPLAY lpDisplay;
{
BUSetPenInvert(lpDisplay);
BUPolyline( lpDisplay, lpDisplay->ptSelBox, 5 );
}
#endif
#ifdef SCCFEATURE_DIALOGS
#ifdef SCCFEATURE_PRINT
WORD OIBNPDoPrintOptions( DoWop )
LPSCCDOPTIONINFO DoWop;
{
//JKXXX return( (WORD)DialogBox(hInst, MAKEINTRESOURCE(OIBPRINTDLG_BOX), DoWop->hParentWnd, (FARPROC)OIBWPrintDlgProc ) );
return(0);
}
WIN_ENTRYSC LRESULT WIN_ENTRYMOD OIBWPrintDlgProc( hDlg, wMsg, wParam, lParam )
HWND hDlg;
UINT wMsg;
WPARAM wParam;
LPARAM lParam;
{
static BOOL bBorder, bWYSIWYG;
HDC hdc;
PAINTSTRUCT ps;
switch ( wMsg )
{
case WM_INITDIALOG:
//JKXXX staticHPrintSample = LoadBitmap( hInst, MAKEINTRESOURCE(OIB_PSAMPLEBITMAP));
OIBWCenterDlg( hDlg );
if( Options.bPrintWYSIWYG )
CheckRadioButton( hDlg, OIBDLG_MAINTAINASPECT, OIBDLG_STRETCH, OIBDLG_MAINTAINASPECT );
else
CheckRadioButton( hDlg, OIBDLG_MAINTAINASPECT, OIBDLG_STRETCH, OIBDLG_STRETCH );
if( Options.bPrintBorder )
CheckDlgButton( hDlg, OIBDLG_BORDER, 1 );
bWYSIWYG = Options.bPrintWYSIWYG;
bBorder = Options.bPrintBorder ;
OIBWUpdatePrintSample( hDlg, NULL, bBorder, bWYSIWYG );
return TRUE;
case WM_PAINT:
hdc = BeginPaint( hDlg, (LPPAINTSTRUCT)&ps );
OIBWUpdatePrintSample( hDlg, hdc, bBorder, bWYSIWYG );
EndPaint( hDlg, &ps );
return TRUE;
case WM_COMMAND:
switch( wParam )
{
case OIBDLG_MAINTAINASPECT:
bWYSIWYG = TRUE;
OIBWUpdatePrintSample( hDlg, NULL, bBorder, bWYSIWYG );
break;
case OIBDLG_STRETCH:
bWYSIWYG = FALSE;
OIBWUpdatePrintSample( hDlg, NULL, bBorder, bWYSIWYG );
break;
case OIBDLG_BORDER:
bBorder = IsDlgButtonChecked( hDlg, OIBDLG_BORDER );
OIBWUpdatePrintSample( hDlg, NULL, bBorder, bWYSIWYG );
break;
case OIBDLG_PRINTHELP:
// JKXXX UTHelp( OI_ImagePrintOptions );
break;
case IDOK:
Options.bPrintWYSIWYG = bWYSIWYG;
Options.bPrintBorder = bBorder;
DeleteObject(staticHPrintSample);
EndDialog ( hDlg, TRUE );
break;
case IDCANCEL:
DeleteObject(staticHPrintSample);
EndDialog ( hDlg, 0 );
break;
}
return TRUE;
}
return FALSE;
}
VOID OIBWUpdatePrintSample( hDlg, hdc, bBorder, bWYSIWYG )
HWND hDlg;
HDC hdc;
BOOL bBorder;
BOOL bWYSIWYG;
{
RECT rcSample;
SOPOINT ptSample;
HANDLE hOldObj;
HDC hMemDc;
WORD wBmpOffset;
BOOL bRelease;
if( hdc == NULL )
{
hdc = GetDC( hDlg );
bRelease = TRUE;
}
else
bRelease = FALSE;
GetWindowRect( GetDlgItem(hDlg,OIBDLG_PRINTSAMPLE), &rcSample );
ptSample.x = (SHORT)rcSample.left;
ptSample.y = (SHORT)(rcSample.top+1);
BUScreenToClient( hDlg, &ptSample );
hMemDc = CreateCompatibleDC( hdc );
if( bWYSIWYG )
wBmpOffset = 0;
else
wBmpOffset = OIB_SAMPLEBMPHEIGHT;
if( bBorder )
wBmpOffset += 2*OIB_SAMPLEBMPHEIGHT;
hOldObj = SelectObject( hMemDc, staticHPrintSample );
BitBlt(hdc, ptSample.x, ptSample.y, OIB_SAMPLEBMPWIDTH, OIB_SAMPLEBMPHEIGHT, hMemDc, 0, wBmpOffset, SRCCOPY);
SelectObject( hMemDc, hOldObj );
rcSample.top = ptSample.y;
rcSample.left = ptSample.x;
rcSample.bottom = ptSample.y + OIB_SAMPLEBMPHEIGHT;
rcSample.right = ptSample.x + OIB_SAMPLEBMPWIDTH;
ValidateRect( hDlg, &rcSample );
DeleteDC( hMemDc );
if( bRelease )
ReleaseDC( hDlg, hdc );
}
#endif // SCCFEATURE_PRINT
#ifdef SCCFEATURE_CLIP
WORD OIBNPDoClipOptions( DoWop )
LPSCCDOPTIONINFO DoWop;
{
//JKXXX return( DialogBox(hInst, MAKEINTRESOURCE(OIBCLIPDLG_BOX), DoWop->hParentWnd, (FARPROC)OIBWClipDlgProc) );
return(0);
}
WIN_ENTRYSC LRESULT WIN_ENTRYMOD OIBWClipDlgProc( hDlg, wMsg, wParam, lParam )
HWND hDlg;
UINT wMsg;
WPARAM wParam;
LPARAM lParam;
{
switch ( wMsg )
{
case WM_INITDIALOG:
OIBWCenterDlg( hDlg );
if( Options.wClipFormats & OIB_CLIPBITMAP )
CheckDlgButton( hDlg, CLIPFORMAT_BITMAP, 1 );
if( Options.wClipFormats & OIB_CLIPDIB )
CheckDlgButton( hDlg, CLIPFORMAT_DIB, 1 );
if( Options.wClipFormats & OIB_CLIPPALETTE )
CheckDlgButton( hDlg, CLIPFORMAT_PALETTE, 1 );
return TRUE;
case WM_COMMAND:
switch ( wParam )
{
case IDOK:
Options.wClipFormats = 0;
if ( IsDlgButtonChecked( hDlg, CLIPFORMAT_BITMAP ) )
Options.wClipFormats |= OIB_CLIPBITMAP;
if ( IsDlgButtonChecked( hDlg, CLIPFORMAT_DIB ) )
Options.wClipFormats |= OIB_CLIPDIB;
if ( IsDlgButtonChecked( hDlg, CLIPFORMAT_PALETTE ) )
Options.wClipFormats |= OIB_CLIPPALETTE;
EndDialog ( hDlg, TRUE );
break;
case OIBDLG_CLIPHELP:
//JKXXX UTHelp( OI_ImageClipOptions );
break;
case IDCANCEL:
EndDialog ( hDlg, 0 );
break;
}
return TRUE;
}
return FALSE;
}
#endif //SCCFEATURE_CLIP
/*
| Shows error messages to the dumb user.
*/
SHORT OIBNPMessageBox( lpDisplay, wMsgId, wCapId )
POIB_DISPLAY lpDisplay;
WORD wMsgId;
WORD wCapId;
{
BYTE szCaption[OIB_CAPTIONMAX];
BYTE szMessage[OIB_MESSAGEMAX];
//JKXX LoadString( hInst, wMsgId, szMessage, OIB_MESSAGEMAX );
if( wCapId != OIB_DEFCAPTION )
{
//JKXXX LoadString( hInst, wCapId, szCaption, OIB_CAPTIONMAX );
return MessageBox( lpDisplay->Gen.hWnd, szMessage, szCaption, MB_OK|MB_ICONSTOP );
}
else
return MessageBox( lpDisplay->Gen.hWnd, szMessage, NULL, MB_OK|MB_ICONSTOP );
}
VOID OIBWCenterDlg( hDlg )
HWND hDlg;
{
RECT locRect;
SHORT locX;
SHORT locY;
GetWindowRect(hDlg,&locRect);
locX = (GetSystemMetrics(SM_CXSCREEN) - (locRect.right - locRect.left)) / 2;
locY = (GetSystemMetrics(SM_CYSCREEN) - (locRect.bottom - locRect.top)) / 2;
SetWindowPos(hDlg,NULL,locX,locY,0,0,SWP_NOSIZE | SWP_NOZORDER);
}
#endif //SCCFEATURE_DIALOGS
/*
| OIBWMapTrueColorBitmap
|
| This routine inspects the pixels of a true color bitmap, mapping them
| to the best fit color in our default 256 color palette. This is done
| with the pre-initialized maps rMap, bMap, and gMap. These maps take
| advantage of our knowledge of where we have placed the colors in the
| palette. The index into the current palette is found by using the RGB
| byte values of each pixel as indices into their respective maps and
| adding the resulting entries.
|
*/
VOID OIBWMapTrueColorBitmap( hdc, pChunkData, lpDisplay, lpTile )
HDC hdc;
LPSTR pChunkData;
POIB_DISPLAY lpDisplay;
POIBTILE lpTile;
{
HPBYTE pSrcData;
HANDLE hMem;
HANDLE hSrcMem;
LPSTR pBits;
LPSTR pDest;
BYTE * locSrcBuf;
BYTE * pSrc;
WORD i,j;
WORD wLineBufSize;
WORD wSrcLineBufSize;
LPBITMAPINFOHEADER lpHead;
WORD wLineSize;
WORD wNumLines;
OIBGetOrgTileExtents( lpDisplay, lpTile, &wLineSize, &wNumLines );
wLineBufSize = OIBScanLineSize( wLineSize, 8, NULL );
wSrcLineBufSize = OIBScanLineSize( wLineSize, 24, NULL );
lpHead = lpDisplay->Image.Np.lpHead;
hMem = UTGlobalAlloc( wLineBufSize * wNumLines );
if( hMem == NULL )
{
lpTile->hBmp = NULL;
return;
}
pBits = UTGlobalLock( hMem );
pSrcData = (HPBYTE) pChunkData;
hSrcMem = LocalAlloc( LMEM_FIXED, wSrcLineBufSize );
locSrcBuf = (BYTE *) LocalLock( hSrcMem );
for( i=0; i< wNumLines; i++ )
{
UTmemcpy( (LPSTR)locSrcBuf, pSrcData, wSrcLineBufSize );
pSrc = locSrcBuf;
pDest = pBits;
for( j=0; j < wLineSize; j++ )
{
*pDest = (BYTE) (bMap[ (WORD) *pSrc ] + gMap[ (WORD) pSrc[1] ] + rMap[ (WORD) pSrc[2] ]);
pSrc += 3;
pDest++;
}
pSrcData += wSrcLineBufSize;
pBits += wLineBufSize;
}
UTGlobalUnlock( hMem );
LocalUnlock( hSrcMem );
LocalFree( hSrcMem );
lpHead->biBitCount = 8;
i = (WORD)lpHead->biClrUsed;
lpHead->biClrUsed = 216;
#ifdef SCCFEATURE_ROTATION
if( lpDisplay->wRotation & OIB_ROTATE90 )
OIBCreateRotatedBmp( lpDisplay, hdc, lpTile, hMem );
else
#endif
OIBNPCreateTileBitmap( lpDisplay, hdc, lpTile, hMem );
lpHead->biBitCount = 24;
lpHead->biClrUsed = (DWORD)i;
}
#ifdef SCCFEATURE_DITHER
VOID OIBWToggleDithering( lpDisplay, hMenu )
POIB_DISPLAY lpDisplay;
HMENU hMenu;
{
CHSECTIONINFO SecInfo;
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
lpDisplay->bDither = !lpDisplay->bDither;
#ifdef SCCFEATURE_MENU
if( lpDisplay->bDither )
CheckMenuItem( hMenu, lpDisplay->Gen.wMenuOffset + OIBMENU_DITHER, MF_BYCOMMAND|MF_CHECKED );
else
CheckMenuItem( hMenu, lpDisplay->Gen.wMenuOffset + OIBMENU_DITHER, MF_BYCOMMAND|MF_UNCHECKED );
#endif
InvalidateRect( lpDisplay->Gen.hWnd, NULL, 1 );
SetCursor( LoadCursor(NULL, IDC_WAIT) );
lpDisplay->ptWinOrg.x = 0;
lpDisplay->ptWinOrg.y = 0;
lpDisplay->wFlags &= ~OIBF_DITHER4BIT;
EnableWindow( lpDisplay->Gen.hHorzScroll, 0 );
EnableWindow( lpDisplay->Gen.hVertScroll, 0 );
SetScrollPos( lpDisplay->Gen.hHorzScroll, SB_CTL, 0, TRUE );
SetScrollPos( lpDisplay->Gen.hVertScroll, SB_CTL, 0, TRUE );
OIBSetScaleValues(lpDisplay, 1);
OIBDeInitDisplay(lpDisplay);
OIBNPInitBitmapInfo( lpDisplay, (PCHSECTIONINFO) &SecInfo );
lpDisplay->Image.wPaletteSize = OIBNPInitPalette( lpDisplay, (PCHSECTIONINFO) &SecInfo );
if( OIBHandleReadAhead( lpDisplay ) )
{
lpDisplay->wFlags |= OIBF_IMAGEPRESENT;
SetCursor( LoadCursor(NULL, IDC_ARROW) );
OIBSetupScrollBars( lpDisplay );
}
}
BOOL OIBWCheckDefaultPalette(lpInfo, wNumColors)
LPBITMAPINFO lpInfo;
WORD wNumColors;
{
LPRGBQUAD pColor;
WORD gb;
WORD i;
if( wNumColors > 16 )
return FALSE;
pColor = (LPRGBQUAD) &(lpInfo->bmiColors);
for( i=0; i < wNumColors; i++ )
{
gb = ((WORD)pColor[i].rgbGreen << 8) | (WORD)(BYTE)pColor[i].rgbBlue;
switch( pColor[i].rgbRed )
{
case 0:
switch( gb )
{
case 0x0000: case 0x00ff: case 0xff00: case 0xffff:
case 0x0080: case 0x8000: case 0x8080:
break;
default:
return FALSE;
}
break;
case 0x80:
switch( gb )
{
case 0x0000: case 0x0080: case 0x8000: case 0x8080:
break;
default:
return FALSE;
}
break;
case 0xFF:
switch( gb )
{
case 0x0000: case 0x00ff: case 0xff00: case 0xffff:
break;
default:
return FALSE;
}
break;
case 0xC0:
if( gb != 0xc0c0 )
return FALSE;
break;
default:
return FALSE;
}
}
return TRUE;
}
#define ADDERROR(x,y) {if((SHORT)((SHORT)(WORD)x+y)<0) x=0;else if((SHORT)((SHORT)(WORD)x+y)>255) x=0xff; else x+=(char)y;}
VOID OIBWDither8Bit( hdc, pChunkData, lpDisplay, lpTile )
HDC hdc;
LPSTR pChunkData;
POIB_DISPLAY lpDisplay;
POIBTILE lpTile;
{
HPBYTE pSrcData;
HANDLE hMem;
HANDLE hSrcMem;
LPSTR pBits;
LPSTR pDest;
BYTE * locSrcBuf;
BYTE * pSrc;
WORD i,j;
WORD wLineBufSize;
WORD wSrcLineBufSize;
BYTE * pWrkBuf;
BYTE * pThisLine;
BYTE * pNextLine;
WORD wLinePos;
WORD wPalIndex;
SHORT err;
PLOGPALETTE pLogPal;
LPPALETTEENTRY pPalette;
LONG lSrcLineInc;
LONG lDestLineInc;
LPBITMAPINFOHEADER lpHead;
WORD wLineSize;
WORD wNumLines;
OIBGetOrgTileExtents( lpDisplay, lpTile, &wLineSize, &wNumLines );
wLineBufSize = OIBScanLineSize( wLineSize, 8, NULL );
wSrcLineBufSize = OIBScanLineSize( wLineSize, 24, NULL );
lpHead = lpDisplay->Image.Np.lpHead;
hMem = UTGlobalAlloc( wLineBufSize * wNumLines );
if( hMem == NULL )
{
lpTile->hBmp = NULL;
return;
}
if( lpDisplay->hDitherBuf == NULL )
lpDisplay->hDitherBuf = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, wSrcLineBufSize * 2 );
pWrkBuf = (BYTE *)LocalLock(lpDisplay->hDitherBuf);
pThisLine = pWrkBuf;
pNextLine = pWrkBuf+wSrcLineBufSize;
pBits = UTGlobalLock( hMem );
// We need to dither in the same direction that the bitmap is defined,
// to get smooth borders between tiles.
if( lpDisplay->Image.wFlags & SO_BOTTOMTOTOP )
{
lSrcLineInc = (LONG)(DWORD)wSrcLineBufSize;
pSrcData = (HPBYTE) pChunkData;
lDestLineInc = (LONG)(DWORD)(wLineBufSize);
}
else
{
lSrcLineInc = 0 - (LONG)(DWORD)wSrcLineBufSize;
pSrcData = (HPBYTE) pChunkData + ((wNumLines-1)*wSrcLineBufSize);
lDestLineInc = 0 - (LONG)(DWORD)(wLineBufSize);
pBits += wLineBufSize * (wNumLines-1);
}
pLogPal = (PLOGPALETTE) LocalLock(lpDisplay->hPalMem);
pPalette = (LPPALETTEENTRY) &(pLogPal->palPalEntry);
hSrcMem = LocalAlloc( LMEM_FIXED, wSrcLineBufSize );
locSrcBuf = (BYTE *) LocalLock( hSrcMem );
UTmemcpy((LPSTR)pThisLine, pSrcData, wSrcLineBufSize );
// Carry over the error values from the previous tile.
if( lpDisplay->Image.wNumTiles )
OIBWCarryError( pThisLine, pNextLine, wSrcLineBufSize );
for( i=0; i< wNumLines; i++ )
{
pSrcData += lSrcLineInc;
if( i < wNumLines -1 )
{
UTmemcpy( (LPSTR)pNextLine, pSrcData, wSrcLineBufSize );
}
else
{
Fill50Percent((LPSTR)pNextLine,wSrcLineBufSize);
}
pSrc = pThisLine;
pDest = pBits;
wLinePos = 0;
wPalIndex = (BYTE) bMap[ (WORD) *pSrc ] + gMap[ (WORD) pSrc[1] ] + rMap[ (WORD) pSrc[2] ];
*pDest = (BYTE)wPalIndex;
// Blue error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peBlue) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos ++ ;
// Carry over green error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peGreen) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos ++;
// Carry over red error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peRed) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos++;
pDest++;
for( j=1; j < wLineSize-1; j++ )
{
// Find best match for current RGB value.
wPalIndex = bMap[ (WORD) *pSrc ] + gMap[ (WORD) pSrc[1] ] + rMap[ (WORD) pSrc[2] ];
*pDest = (BYTE) wPalIndex;
// Carry over blue error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peBlue) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
ADDERROR(pNextLine[wLinePos+3], err);
// Carry over green error
pSrc++;
wLinePos ++ ;
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peGreen) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
ADDERROR(pNextLine[wLinePos+3], err);
// Carry over red error
pSrc++;
wLinePos ++;
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peRed) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
ADDERROR(pSrc[3], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
ADDERROR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos++;
pDest++;
}
wPalIndex = (BYTE) bMap[ (WORD) *pSrc ] + gMap[ (WORD) pSrc[1] ] + rMap[ (WORD) pSrc[2] ];
*pDest = (BYTE)wPalIndex;
// Blue error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peBlue) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
pSrc++;
wLinePos ++ ;
// Carry over green error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peGreen) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
pSrc++;
wLinePos ++;
// Carry over red error
err = (SHORT)(pSrc[0]-pPalette[wPalIndex].peRed) * 3 / 8;
ADDERROR(pNextLine[wLinePos], err);
err /= 3;
ADDERROR(pNextLine[wLinePos-3], err);
pSrc++;
wLinePos++;
pDest++;
pWrkBuf = pThisLine;
pThisLine = pNextLine;
pNextLine = pWrkBuf;
pBits += lDestLineInc;
}
// Make sure leftover error values are in the top of the dither buffer.
UTmemcpy( pNextLine, pThisLine, wSrcLineBufSize );
LocalUnlock(lpDisplay->hPalMem);
LocalUnlock( hSrcMem );
LocalFree( hSrcMem );
LocalUnlock(lpDisplay->hDitherBuf);
UTGlobalUnlock( hMem );
lpHead->biBitCount = 8;
i = (WORD)lpHead->biClrUsed;
lpHead->biClrUsed = 216;
if( lpDisplay->wRotation & OIB_ROTATE90 )
OIBCreateRotatedBmp( lpDisplay, hdc, lpTile, hMem );
else
OIBNPCreateTileBitmap( lpDisplay, hdc, lpTile, hMem );
lpHead->biBitCount = 24;
lpHead->biClrUsed = (DWORD)i;
}
#define ADDINTERR(x,y) {if((x+y)<0) x=0;else if((x+y)>255) x=0x00ff; else x+=y;}
// #define ADDINTERR(x,y) x+=y
VOID OIBWDither4Bit( hdc, pChunkData, lpDisplay, lpTile )
HDC hdc;
LPSTR pChunkData;
POIB_DISPLAY lpDisplay;
POIBTILE lpTile;
{
HPBYTE pSrcData;
HANDLE hMem;
LPSTR pBits;
LPSTR pDest;
WORD i,j;
WORD wLineBufSize;
WORD wSrcLineBufSize;
WORD wWrkLineBufSize;
LPBITMAPINFO lpDocInfo;
LPBITMAPINFOHEADER lpHead;
WORD wOrgBitCount;
LPRGBQUAD pSrcColor;
SHORT * pWrkBuf;
SHORT * pSrc;
SHORT * pThisLine;
SHORT * pNextLine;
WORD wLinePos;
WORD wPalIndex;
SHORT err, err1;
HANDLE hTempLineBuf;
BYTE * pTempLine;
BYTE * pTempDest;
LONG lSrcLineInc;
LONG lDestLineInc;
SHORT * Red, *Green, *Blue;
WORD wLineSize;
WORD wNumLines;
OIBGetOrgTileExtents( lpDisplay, lpTile, &wLineSize, &wNumLines );
wOrgBitCount = lpDisplay->Image.wBitCount;
lpHead = lpDisplay->Image.Np.lpHead;
wLineBufSize = OIBScanLineSize( wLineSize, 4, NULL );
wSrcLineBufSize = OIBScanLineSize( wLineSize, wOrgBitCount, NULL );
wWrkLineBufSize = 3*wLineSize;
hMem = UTGlobalAlloc( wLineBufSize * wNumLines );
if( lpDisplay->hDitherBuf == NULL )
{
lpDisplay->hDitherBuf = LocalAlloc( LMEM_MOVEABLE | LMEM_ZEROINIT, wWrkLineBufSize * 2 *sizeof(SHORT));
OIBWInitColorBuf( lpDisplay, 16 );
}
hTempLineBuf = UTLocalAlloc( wLineSize+1 );
if( hMem == NULL || lpDisplay->hDitherBuf==NULL || hTempLineBuf == NULL || lpDisplay->hColorBuf == NULL )
{
lpTile->hBmp = NULL;
return;
}
// We need to dither in the same direction that the bitmap is defined,
// in order to get smooth borders between tiles.
pBits = UTGlobalLock( hMem );
if( lpDisplay->Image.wFlags & SO_BOTTOMTOTOP )
{
lSrcLineInc = (LONG)(DWORD)wSrcLineBufSize;
pSrcData = (HPBYTE) pChunkData;
lDestLineInc = (LONG)(DWORD)wLineBufSize;
}
else
{
lSrcLineInc = 0 - (LONG)(DWORD)wSrcLineBufSize;
pSrcData = (HPBYTE) pChunkData + ((wNumLines-1)*wSrcLineBufSize);
lDestLineInc = 0 - (LONG)(DWORD)(wLineBufSize);
pBits += wLineBufSize * (wNumLines-1);
}
Red = (SHORT *)LocalLock(lpDisplay->hColorBuf);
Blue = Red+16;
Green = Blue+16;
pWrkBuf = (SHORT *)LocalLock(lpDisplay->hDitherBuf);
pThisLine = pWrkBuf;
pNextLine = pWrkBuf+wWrkLineBufSize;
pTempLine = (BYTE *)LocalLock(hTempLineBuf);
lpDocInfo = (LPBITMAPINFO) GlobalLock(lpDisplay->Image.Np.hDocBmpInfo);
pSrcColor = (LPRGBQUAD) &(lpDocInfo->bmiColors);
OIBWGetRGBLineData( pThisLine, (HPBYTE)pSrcData, wLineSize, pSrcColor, wOrgBitCount );
// Carry over error values from previous tile.
if( lpDisplay->Image.wNumTiles )
OIBWCarryINTError( pThisLine, pNextLine, wWrkLineBufSize );
for( i=0; i< wNumLines; i++ )
{
pSrcData += lSrcLineInc;
if( i < wNumLines -1 )
OIBWGetRGBLineData( pNextLine, (HPBYTE)pSrcData, wLineSize, pSrcColor, wOrgBitCount );
else
Fill50PercentINT(pNextLine,wWrkLineBufSize);
pSrc = pThisLine;
pTempDest = pTempLine;
wLinePos = 0;
wPalIndex = GetClosest4BitColor( (WORD)pSrc[2], (WORD)pSrc[1], (WORD)pSrc[0]);
*pTempDest++ = (BYTE)wPalIndex;
// Blue error
err1 = (pSrc[0] - Blue[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos ++ ;
// Carry over green error
err1 = (pSrc[0]-Green[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos ++;
// Carry over red error
err1 = (pSrc[0]-Red[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos++;
for( j=1; j < wLineSize-1; j++ )
{
// Find best match for current RGB value.
wPalIndex = GetClosest4BitColor( (WORD)pSrc[2], (WORD)pSrc[1], (WORD)pSrc[0]);
*pTempDest++ = (BYTE)wPalIndex;
// Carry over blue error
err1 = (pSrc[0]-Blue[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos-3], err);
ADDINTERR(pNextLine[wLinePos+3], err);
// Carry over green error
pSrc++;
wLinePos ++ ;
err1 = (pSrc[0]-Green[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos-3], err);
ADDINTERR(pNextLine[wLinePos+3], err);
// Carry over red error
pSrc++;
wLinePos ++;
err1 = (pSrc[0]-Red[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pSrc[3], err);
err = err1 >> 3;
ADDINTERR(pNextLine[wLinePos-3], err);
ADDINTERR(pNextLine[wLinePos+3], err);
pSrc++;
wLinePos++;
}
wPalIndex = GetClosest4BitColor( (WORD)pSrc[2], (WORD)pSrc[1], (WORD)pSrc[0]);
*pTempDest++ = (BYTE)wPalIndex;
// Blue error
err1 = (pSrc[0]-Blue[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pNextLine[wLinePos-3], (err1 >> 3));
pSrc++;
wLinePos ++ ;
// Carry over green error
err1 = (pSrc[0]-Green[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pNextLine[wLinePos-3], (err1 >> 3));
pSrc++;
wLinePos ++;
// Carry over red error
err1 = (pSrc[0]-Red[wPalIndex]);
err = (err1 * 3) >> 3;
ADDINTERR(pNextLine[wLinePos], err);
ADDINTERR(pNextLine[wLinePos-3], (err1 >> 3));
pSrc++;
wLinePos++;
pWrkBuf = pThisLine;
pThisLine = pNextLine;
pNextLine = pWrkBuf;
// Now take the temporary line and create a 4-bit per pixel line.
pDest = pBits;
for( j = 0; j < wLineSize; j += 2 )
*pDest++ = MAKEBYTE(pTempLine[j],pTempLine[j+1]);
pBits += lDestLineInc;
}
// Make sure leftover error values are in the top of the dither buffer.
UTmemcpy( (LPSTR)pNextLine, (LPSTR)pThisLine, wWrkLineBufSize*sizeof(SHORT) );
LocalUnlock(lpDisplay->hColorBuf);
GlobalUnlock(lpDisplay->Image.Np.hDocBmpInfo);
LocalUnlock(lpDisplay->hDitherBuf);
LocalUnlock(hTempLineBuf);
LocalFree(hTempLineBuf);
// Reset pBits pointer.
UTGlobalUnlock( hMem );
lpHead->biBitCount = 4;
j=(WORD)lpHead->biClrUsed;
lpHead->biClrUsed = 0;
if( lpDisplay->wRotation & OIB_ROTATE90 )
OIBCreateRotatedBmp( lpDisplay, hdc, lpTile, hMem );
else
OIBNPCreateTileBitmap( lpDisplay, hdc, lpTile, hMem );
lpHead->biBitCount = (SHORT)wOrgBitCount;
lpHead->biClrUsed = j;
}
VOID OIBWCarryINTError( pDest, pSrc, wSize )
SHORT * pDest;
SHORT * pSrc;
WORD wSize;
{
SHORT err;
WORD i;
for( i=0; i < wSize; i++ )
{
err = (SHORT)(WORD)pSrc[i] - 0x0080;
ADDINTERR( pDest[i], err );
}
}
VOID OIBWCarryError( pDest, pSrc, wSize )
BYTE * pDest;
BYTE * pSrc;
WORD wSize;
{
SHORT err;
WORD i;
for( i=0; i < wSize; i++ )
{
err = (SHORT)(WORD)pSrc[i] - 0x80;
ADDERROR( pDest[i], err );
}
}
VOID OIBWGetRGBLineData( pDest, pSrc, wNumPix, pSrcColor, wBitCount )
SHORT * pDest;
HPBYTE pSrc;
WORD wNumPix;
LPRGBQUAD pSrcColor;
WORD wBitCount;
{
WORD i;
WORD bOdd;
WORD pix1, pix2;
if( wBitCount == 24 )
{
wNumPix *= 3;
for(i=0; i<wNumPix; i++ )
*pDest++ = (SHORT)(WORD)(BYTE)*pSrc++;
}
else if( wBitCount == 8 )
{
for(i=0; i<wNumPix; i++ )
{
pix1 = (WORD)(BYTE)*pSrc++;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbBlue;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbGreen;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbRed;
}
}
else if( wBitCount == 4 )
{
if( wNumPix % 2 )
{
bOdd = TRUE;
wNumPix--;
}
else
bOdd = FALSE;
for(i=0; i<wNumPix; i+= 2 )
{
pix1 = HIGHNIBBLE(*pSrc);
pix2 = LOWNIBBLE(*pSrc);
pSrc++;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbBlue;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbGreen;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbRed;
*pDest++ = (SHORT)(WORD)pSrcColor[pix2].rgbBlue;
*pDest++ = (SHORT)(WORD)pSrcColor[pix2].rgbGreen;
*pDest++ = (SHORT)(WORD)pSrcColor[pix2].rgbRed;
}
if( bOdd )
{
pix1 = HIGHNIBBLE(*pSrc);
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbBlue;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbGreen;
*pDest++ = (SHORT)(WORD)pSrcColor[pix1].rgbRed;
}
}
}
VOID OIBWInitColorBuf(lpDisplay, wNumColors )
POIB_DISPLAY lpDisplay;
WORD wNumColors;
{
PLOGPALETTE pLogPal;
LPPALETTEENTRY pPalette;
WORD i;
SHORT * Red, * Green, * Blue;
lpDisplay->hColorBuf = LocalAlloc( LMEM_MOVEABLE|LMEM_ZEROINIT, wNumColors*3*sizeof(SHORT) );
if( lpDisplay->hColorBuf != NULL )
{
pLogPal = (PLOGPALETTE) LocalLock(lpDisplay->hPalMem);
pPalette = (LPPALETTEENTRY) &(pLogPal->palPalEntry);
Red = (SHORT *)LocalLock(lpDisplay->hColorBuf);
Blue = Red+wNumColors;
Green = Blue+wNumColors;
for(i=0; i<16; i++)
{
Red[i] = pPalette[i].peRed;
Green[i] = pPalette[i].peGreen;
Blue[i] = pPalette[i].peBlue;
}
GlobalUnlock(lpDisplay->hPalMem);
LocalUnlock(lpDisplay->hColorBuf);
}
}
VOID Fill50Percent( pBuf, wCount )
LPSTR pBuf;
WORD wCount;
{
while( wCount > 0 )
{
*pBuf++ = (BYTE)0x0080;
wCount--;
}
}
VOID Fill50PercentINT( pBuf, wCount )
SHORT *pBuf;
WORD wCount;
{
while( wCount > 0 )
{
*pBuf++ = 0x0080;
wCount--;
}
}
#endif // SCCFEATURE_DITHER
/*
| OIBWGenDefault256Palette
|
| This function generates a default 256 color palette, which is used to
| display true color images. This new version really only generates
| 216 colors, using 6 levels each of red, green and blue. Since Windows
| reserves 20 colors for itself, this assures us that we won't have
| any of our colors replaced by a system color. Hopefully, this means
| that our dithering will be free of errors introduced by Windows
| switching colors on us.
|
| This allows us to use our knowledge of the palette's layout to
| optimally map true colors to the palette ourselves, which turns out
| to take a fraction of the time Windows needs to do the same mapping.
*/
VOID OIBWGenDefault256Palette( lpInfo, hdc, pPalette )
LPBITMAPINFO lpInfo;
HDC hdc;
LPPALETTEENTRY pPalette;
{
BYTE rVal;
BYTE gVal;
BYTE bVal;
WORD i, j, k, wPalEntry;
wPalEntry = 0;
rVal = 0;
for( i=0; i<6; i++ )
{
gVal = 0;
for( j=0; j<6; j++ )
{
bVal = 0;
for( k=0; k<6; k++ )
{
pPalette[wPalEntry].peRed = rVal;
pPalette[wPalEntry].peGreen = gVal;
pPalette[wPalEntry].peBlue = bVal;
pPalette[wPalEntry].peFlags = PC_NOCOLLAPSE;
wPalEntry++;
bVal += 51;
}
gVal += 51;
}
rVal += 51;
}
}
/*
| OIBWGenTrueColorMap
|
| This routine generates the maps used by OIBWMapTrueColorBitmap.
| Obviously, this routine is related to the one above, which creates
| the palette.
*/
VOID OIBWGenTrueColorMap()
{
WORD i;
WORD rVal = 0;
WORD gVal = 0;
WORD bVal = 0;
WORD wCutoff = 25;
// "wCutoff" is the halfway point in a range of color values, where the
// current color becomes closer to the next color level than the current
// color level.
for( i=0; i<256; i++ )
{
if( i == wCutoff )
{
wCutoff += 51;
bVal++;
gVal += 6;
rVal += 36;
}
bMap[i] = bVal;
gMap[i] = gVal;
rMap[i] = rVal;
}
}
VOID OIBWGetDefault16Palette( pEntries )
LPPALETTEENTRY pEntries;
{
WORD i,j,k;
BYTE val;
val = 0x80;
k=0;
for( i=0;i<2;i++ )
{
for(j=0;j<8; j++ )
{
pEntries[k].peRed = (j&0x01) ? val : 0;
pEntries[k].peGreen = (j&0x02) ? val : 0;
pEntries[k++].peBlue = (j&0x04) ? val : 0;
}
val = 0xff;
}
pEntries[8] = pEntries[7];
pEntries[7].peRed = 0xc0;
pEntries[7].peGreen = 0xc0;
pEntries[7].peBlue = 0xc0;
}
// This routine attempts to be a faster color mapper than Windows.
// Not too freaking hard, really.
WORD GetClosest4BitColor( r,g,b )
WORD r;
WORD g;
WORD b;
{
DWORD d1;
DWORD d2;
WORD ret;
DWORD r1, g1, b1;
DWORD r2, g2, b2;
// Macro for the square of the difference between 2 numbers.
#define SQ_DIFF(x,y) (DWORD)((LONG)((LONG)x-(LONG)y)*(LONG)((LONG)x-(LONG)y))
r1 = (DWORD)(r*r);
g1 = (DWORD)(g*g);
b1 = (DWORD)(b*b);
r2 = SQ_DIFF(0x0080,r);
g2 = SQ_DIFF(0x0080,g);
b2 = SQ_DIFF(0x0080,b);
ret = 0;
d1 = r1+g1+b1; // 0,0,0
d2 = r2+g1+b1;
if( d2<d1 ) { d1=d2; ret = 1;} // 80,0,0
d2 = r1+g2+b1;
if( d2<d1 ) { d1=d2; ret = 2;} // 0,80,0
d2 = r2+g2+b1;
if( d2<d1 ) { d1=d2; ret = 3;} // 80,80,0
d2 = r1+g1+b2;
if( d2<d1 ) { d1=d2; ret = 4;} // 0,0,80
d2 = r2+g1+b2;
if( d2<d1 ) { d1=d2; ret = 5;} // 80,0,80
d2 = r1+g2+b2;
if( d2<d1 ) { d1=d2; ret = 6;} // 0,80,80
d2 = r2+g2+b2;
if( d2<d1 ) { d1=d2; ret = 8;} // 80,80,80
// Now compare to light gray.
r2 = SQ_DIFF(0x00C0,r);
g2 = SQ_DIFF(0x00C0,g);
b2 = SQ_DIFF(0x00C0,b);
d2 = r2+g2+b2;
if( d2<d1 ) { d1=d2; ret = 7;}
else if( d1 < 0x1000 ) return ret; // No remaining point in color space can be closer.
// Light shades.
r2 = SQ_DIFF(0x00FF,r);
g2 = SQ_DIFF(0x00FF,g);
b2 = SQ_DIFF(0x00FF,b);
d2 = r2+g1+b1;
if( d2<d1 ) { d1=d2; ret = 9;} // ff,0,0
d2 = r1+g2+b1;
if( d2<d1 ) { d1=d2; ret = 10;} // 0,ff,0
d2 = r2+g2+b1;
if( d2<d1 ) { d1=d2; ret = 11;} // ff,ff,0
d2 = r1+g1+b2;
if( d2<d1 ) { d1=d2; ret = 12;} // 0,0,ff
d2 = r2+g1+b2;
if( d2<d1 ) { d1=d2; ret = 13;} // ff,0,ff
d2 = r1+g2+b2;
if( d2<d1 ) { d1=d2; ret = 14;} // 0,ff,ff
d2 = r2+g2+b2;
if( d2<d1 ) { d1=d2; ret = 15;} // ff,ff,ff
return ret;
}
/*--------------------------------------------------------------------
The routines below provide a 16-bit GDI unit to 32-bit GDI unit layer
to the routines which use pointers to int or pointers to rects. Long
term we need to "virtualize" the GDI basic unit size. That will take a
little bit more work.
---------------------------------------------------------------------*/
BOOL Win32Fixup ( lpFix, lpInt, nCount )
PFIXUP lpFix;
LPSHORT lpInt;
SHORT nCount;
{
SHORT i;
lpFix->hData = UTGlobalAlloc( sizeof(int)*nCount );
lpFix->pInt = NULL;
if ( lpFix->hData )
{
lpFix->pInt = UTGlobalLock(lpFix->hData);
for (i=0; i<nCount; i++ )
lpFix->pInt[i] =lpInt[i];
return(1);
}
else
return(0);
}
BOOL Win32FreeFixup ( lpFix )
PFIXUP lpFix;
{
UTGlobalUnlock(lpFix->hData);
UTGlobalFree(lpFix->hData);
return(1);
}
BOOL Win32LPtoDP(hDC,lpPt,n)
HDC hDC;
PSOPOINT lpPt;
SHORT n;
{
FIXUP Fix;
if(Win32Fixup(&Fix,(LPSHORT)lpPt,(SHORT)(n*2)))
{
LPSHORT lpShort;
SHORT i;
LPtoDP(hDC,(LPPOINT)Fix.pInt,n);
lpShort = (LPSHORT)lpPt;
for (i=0; i < n*2; i++)
lpShort[i] = Fix.pInt[i];
Win32FreeFixup(&Fix);
return(1);
}
else
return(0);
}
BOOL Win32DPtoLP(hDC,lpPt,n)
HDC hDC;
PSOPOINT lpPt;
SHORT n;
{
FIXUP Fix;
if(Win32Fixup(&Fix,(LPSHORT)lpPt,(SHORT)(n*2)))
{
LPSHORT lpShort;
SHORT i;
DPtoLP(hDC,(LPPOINT)Fix.pInt,n);
lpShort = (LPSHORT)lpPt;
for (i=0; i < n*2; i++)
lpShort[i] = Fix.pInt[i];
Win32FreeFixup(&Fix);
return(1);
}
else
return(0);
}
BOOL Win32ScreenToClient(hWnd,lpPt)
HWND hWnd;
PSOPOINT lpPt;
{
POINT Pt;
ScreenToClient(hWnd,&Pt);
lpPt->x = (SHORT)Pt.x;
lpPt->y = (SHORT)Pt.y;
return(1);
}
BOOL Win32GetCursorPos(lpPt)
PSOPOINT lpPt;
{
POINT Pt;
GetCursorPos(&Pt);
lpPt->x = (SHORT)Pt.x;
lpPt->y = (SHORT)Pt.y;
return(1);
}
BOOL Win32Polyline(hDC,lpPoint,nPoints)
HDC hDC;
PSOPOINT lpPoint;
SHORT nPoints;
{
BOOL Ret;
FIXUP Fix;
if(Win32Fixup(&Fix,(LPSHORT)lpPoint,(SHORT)(nPoints*2)))
{
Ret = Polyline(hDC,(LPPOINT)Fix.pInt,nPoints);
Win32FreeFixup(&Fix);
}
else
Ret=0;
return(Ret);
}
BOOL Win32PtInRect(lpRect,Point)
LPRECT lpRect;
SOPOINT Point;
{
POINT Pt;
Pt.x = Point.x;
Pt.y = Point.y;
return(PtInRect(lpRect,Pt));
}