mirror of https://github.com/lianthony/NT4.0
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.
1802 lines
72 KiB
1802 lines
72 KiB
/****************************************************************************
|
|
ANBITMAP.C
|
|
|
|
$Log: S:\products\msprods\oiwh\display\anbitmap.c_v $
|
|
*
|
|
* Rev 1.36 20 Jun 1996 16:01:20 RC
|
|
* Fixed resize of image and text marks
|
|
*
|
|
* Rev 1.35 16 Apr 1996 15:24:28 BEG06016
|
|
* Added #ifdef IN_PROG_CHANNEL_SAFARI.
|
|
*
|
|
* Rev 1.34 15 Apr 1996 11:03:38 RC
|
|
* Fixed freeing of the display dib every time in BitsTransparent
|
|
*
|
|
* Rev 1.33 11 Apr 1996 15:12:14 BEG06016
|
|
* Optimized named block access some.
|
|
*
|
|
* Rev 1.32 17 Jan 1996 13:58:58 RC
|
|
* Changed scalealgstruct.uimageflags to be assigned pimage->nrwdatatype
|
|
* from pimage->pimg->ntype (in PaintAnnotationBitmap)
|
|
*
|
|
* Rev 1.31 10 Jan 1996 11:53:54 RC
|
|
* Fixed a bad pointer in BitsTransparent
|
|
*
|
|
* Rev 1.30 02 Jan 1996 14:10:42 BLJ
|
|
* Fixed bug in BW_AVG_TO_BW scale algorithm.
|
|
*
|
|
* Rev 1.29 02 Jan 1996 09:56:18 BLJ
|
|
* Changed alot of UINTs to ints.
|
|
* Changed IMG structure to include the image data.
|
|
* Changed lp prefix to p.
|
|
*
|
|
* Rev 1.28 22 Dec 1995 11:15:02 RC
|
|
* Passed in palette to scalebits in ipscaling
|
|
*
|
|
* Rev 1.27 22 Dec 1995 11:10:44 BLJ
|
|
* Added a parameter for zero init'ing to some memory manager calls.
|
|
*
|
|
* Rev 1.26 29 Nov 1995 14:18:28 RC
|
|
* Passed in both horiz and vert scales into ipscaling
|
|
*
|
|
* Rev 1.25 08 Nov 1995 11:12:34 RC
|
|
* Took out PAINT_MODE_SELECTED flag as its function is now performed by
|
|
* PaintHandles
|
|
*
|
|
* Rev 1.24 18 Oct 1995 15:15:22 RC
|
|
* Changed image marks to be non scale to gray if they are not b&w, no matter
|
|
* what happens to the base image
|
|
*
|
|
* Rev 1.23 13 Oct 1995 12:27:12 RAR
|
|
* Use StretchDIBits() instead of Rectangle() for non-highlighted filled
|
|
* rectangles (only when printing). Work around for printer drivers (HPLJ4
|
|
* drivers) that ignore SetROP2() drawing mode.
|
|
****************************************************************************/
|
|
|
|
#include "privdisp.h"
|
|
|
|
/******************************************************************************
|
|
|
|
FUNCTION: IPScaling
|
|
|
|
PURPOSE: To scale the dib with IPpack scaling and then blt
|
|
it to the DC passed in
|
|
|
|
*********************************************************************************/
|
|
int WINAPI IPScaling(HDC hDC, PBITMAPINFOHEADER pDib, LRECT lrScaledRect,
|
|
int nHScale, int nVScale, PAN_NEW_ROTATE_STRUCT pAnRotation,
|
|
LRECT lrDestPt, PIMAGE pImage, BOOL transparent,
|
|
int mode, int nScaleAlgorithm,
|
|
PMARK pMark, PPSTR ppgray){
|
|
|
|
int nStatus = 0;
|
|
|
|
HBITMAP hBitmap = 0;
|
|
HBITMAP hOldBitmap = 0;
|
|
HDC hdcmem = 0;
|
|
PIMG pDestImg = 0;
|
|
PIMG pHidImage = 0;
|
|
RECT rRect;
|
|
LRECT lrRect;
|
|
PBITMAPINFOHEADER pNewDib = 0;
|
|
int nSize;
|
|
|
|
|
|
// to avoid divide by 0 errors
|
|
if (lrScaledRect.right == 0)
|
|
lrScaledRect.right = 1;
|
|
if (lrScaledRect.bottom == 0)
|
|
lrScaledRect.bottom = 1;
|
|
|
|
// convert dib to ippack image (pHidImage)
|
|
CheckError2(DibToIpNoPal(&pHidImage, pDib))
|
|
|
|
// modes 1 and 2 are for bitblting when the image is ready. All
|
|
// scale to gray and other stuff has already been done to the image
|
|
if ((mode == 1) || (mode == 2)){
|
|
pNewDib = pDib;
|
|
goto NoScaleToGray;
|
|
}
|
|
|
|
// convert the image to a displayable format at the right scale.
|
|
|
|
switch (nScaleAlgorithm){
|
|
case OI_SCALE_ALG_USE_DEFAULT:
|
|
case OI_SCALE_ALG_NORMAL:
|
|
case OI_SCALE_ALG_STAMP:
|
|
CheckError2(CreateAnyImgBuf(&pDestImg,
|
|
(lrScaledRect.right - lrScaledRect.left),
|
|
(lrScaledRect.bottom - lrScaledRect.top), pHidImage->nType))
|
|
break;
|
|
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
|
|
CheckError2(CreateAnyImgBuf(&pDestImg,
|
|
(lrScaledRect.right - lrScaledRect.left),
|
|
(lrScaledRect.bottom - lrScaledRect.top), ITYPE_GRAY4))
|
|
break;
|
|
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
|
|
CheckError2(CreateAnyImgBuf(&pDestImg,
|
|
(lrScaledRect.right - lrScaledRect.left),
|
|
(lrScaledRect.bottom - lrScaledRect.top), ITYPE_GRAY7))
|
|
break;
|
|
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
|
|
CheckError2(CreateAnyImgBuf(&pDestImg,
|
|
(lrScaledRect.right - lrScaledRect.left),
|
|
(lrScaledRect.bottom - lrScaledRect.top), ITYPE_GRAY8))
|
|
break;
|
|
case OI_SCALE_ALG_BW_MINORITY:
|
|
case OI_SCALE_ALG_BW_MAJORITY:
|
|
case OI_SCALE_ALG_BW_AVERAGE_TO_BW:
|
|
CheckError2(CreateAnyImgBuf(&pDestImg,
|
|
(lrScaledRect.right - lrScaledRect.left),
|
|
(lrScaledRect.bottom - lrScaledRect.top), ITYPE_BI_LEVEL))
|
|
break;
|
|
default:
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
|
|
CopyRect(lrRect, lrScaledRect);
|
|
ConvertRect2(&lrRect, CONV_SCALED_TO_FULLSIZE, nHScale, nVScale, 0, 0);
|
|
|
|
CheckError2(ScaleBits(pHidImage, pDestImg, nScaleAlgorithm,
|
|
nHScale, nVScale, lrRect, lrScaledRect,
|
|
(LPRGBQUAD) ((PSTR) pDib + sizeof(BITMAPINFOHEADER))))
|
|
|
|
SetRect(&rRect, 0, 0, pDestImg->nWidth, pDestImg->nHeight);
|
|
|
|
// Convert scaled ippack image to a dib
|
|
CheckError2(IPtoDIB(pImage, pDestImg, &pNewDib, rRect))
|
|
// Copy palette info from old dib to new dib
|
|
if (pHidImage->nType == pDestImg->nType){
|
|
memcpy((PSTR) pNewDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR) pDib + sizeof(BITMAPINFOHEADER), ((int) pDib->biClrUsed*4));
|
|
}
|
|
NoScaleToGray:
|
|
if (mode != 4){ // if transparent blt, dont do
|
|
hBitmap = CreateCompatibleBitmap (hDC, (int) pNewDib->biWidth,
|
|
(int) pNewDib->biHeight);
|
|
hdcmem = CreateCompatibleDC (hDC);
|
|
if (!SetDIBits (hDC, hBitmap, 0, (int) pNewDib->biHeight,
|
|
(PSTR) pNewDib + sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed*4),
|
|
(PBITMAPINFO) pNewDib, DIB_RGB_COLORS)){
|
|
nStatus = Error(DISPLAY_GETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
hOldBitmap = SelectObject (hdcmem, hBitmap);
|
|
}
|
|
// Now blt the scaled dib to the DC
|
|
if (!transparent){
|
|
if (mode == 4){
|
|
*ppgray = (PSTR) pNewDib;
|
|
goto Exit;
|
|
}
|
|
if (!BitBlt (hDC, (int)lrDestPt.left, (int)lrDestPt.top,
|
|
(int) pNewDib->biWidth, (int) pNewDib->biHeight, hdcmem, 0, 0, SRCCOPY)){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (mode == 3){
|
|
// Replace old szOiDIB with new pNewDib;
|
|
nSize = sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage);
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pNewDib, nSize))
|
|
}
|
|
}else{ // transparent blt
|
|
// the modes are set by BitsTransparent to blt the mask and then
|
|
// the image
|
|
if (mode == 1){
|
|
if (!BitBlt (hDC, (int)lrDestPt.left, (int)lrDestPt.top,
|
|
(int) pNewDib->biWidth, (int) pNewDib->biHeight, hdcmem, 0, 0, SRCAND)){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
}else if (mode == 2){
|
|
if (!BitBlt (hDC, (int)lrDestPt.left, (int)lrDestPt.top,
|
|
(int) pNewDib->biWidth, (int) pNewDib->biHeight, hdcmem, 0, 0, SRCPAINT)){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (nStatus || ((mode != 1) && (mode !=2) && (mode != 3) && (mode != 4))){
|
|
// Free temporary dib, if not the mode in which it is saved to the mark
|
|
FreeMemory((PPSTR) &pNewDib);
|
|
}
|
|
if (hOldBitmap){
|
|
SelectObject(hdcmem, hOldBitmap);
|
|
}
|
|
if (hBitmap){
|
|
DeleteObject(hBitmap);
|
|
}
|
|
if (hdcmem){
|
|
DeleteDC(hdcmem);
|
|
}
|
|
FreeImgBuf(&pHidImage);
|
|
FreeImgBuf(&pDestImg);
|
|
|
|
return (nStatus);
|
|
}
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: BitsTransparent
|
|
|
|
PURPOSE: Makes RGB(255,255,255) portion of image transparent
|
|
|
|
******************************************************************************/
|
|
|
|
int WINAPI BitsTransparent(HDC hDC, PBITMAPINFOHEADER pDib,
|
|
LRECT lrScaledRect, PAN_NEW_ROTATE_STRUCT pAnRotation,
|
|
LRECT lrDestPt, int nMode, PIMAGE pImage,
|
|
int nHScale, int nVScale, int nScaleAlgorithm, PMARK pMark){
|
|
|
|
int nStatus = 0;
|
|
|
|
RGBQUAD FAR* pRGB;
|
|
RGBQUAD FAR* pRGB1 = 0;
|
|
int n;
|
|
ulong ByteColor;
|
|
BYTE huge* hpByte;
|
|
BYTE huge* hpRGB1 = 0;
|
|
BYTE huge* hpRGB;
|
|
int nRopCode;
|
|
int nOldROP;
|
|
HBRUSH hOldBrush;
|
|
HPEN hOldPen;
|
|
BOOL transparent;
|
|
int mode;
|
|
HDC hLocalDC = 0;// this is just a dummy dc
|
|
PSTR pgray=0;
|
|
PBITMAPINFOHEADER pNewDib ;
|
|
|
|
switch (nMode){
|
|
case PAINT_MODE_DRAG:
|
|
case PAINT_MODE_XOR:
|
|
nRopCode = R2_XORPEN;
|
|
break;
|
|
|
|
case PAINT_MODE_NORMAL:
|
|
nRopCode = R2_COPYPEN;
|
|
break;
|
|
}
|
|
nOldROP = SetROP2(hDC, nRopCode);
|
|
|
|
if ((nMode == PAINT_MODE_DRAG) || (nMode == PAINT_MODE_XOR)){
|
|
// if image is dragged, draw a rect the size of the image
|
|
// and then fall through (actual bit manipulation not needed)
|
|
hOldPen = SelectObject(hDC, GetStockObject(NULL_PEN));
|
|
hOldBrush = SelectObject(hDC, GetStockObject(GRAY_BRUSH));
|
|
Rectangle (hDC, (int)lrDestPt.left, (int)lrDestPt.top, (int)lrDestPt.left
|
|
+ (int)(lrScaledRect.right-lrScaledRect.left),
|
|
(int)lrDestPt.top + (int)(lrScaledRect.bottom-lrScaledRect.top));
|
|
SelectObject(hDC, hOldBrush);
|
|
SelectObject(hDC, hOldPen);
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pDib->biClrUsed == 0) && (pDib->biBitCount != 24)){
|
|
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
|
|
goto Exit;
|
|
}
|
|
// this stuff does the scaling and we get the scaled dib back as pNewDib
|
|
// No blting to the dc is done in this ipscaling call
|
|
transparent = FALSE;
|
|
mode = 4;
|
|
CheckError2(IPScaling(hLocalDC, pDib, lrScaledRect, nHScale, nVScale,
|
|
pAnRotation, lrDestPt, pImage, transparent, mode,
|
|
nScaleAlgorithm, pMark, &pgray))
|
|
pNewDib = (PBITMAPINFOHEADER) pgray;
|
|
// if it is 24-bit color bitmap (1, 4 & 8bits will fail earlier)
|
|
if (pNewDib->biClrUsed == 0){
|
|
// for transparency, a copy of the original bits must be saved
|
|
CheckError2(AllocateMemory(pNewDib->biSizeImage, (PPSTR) &hpRGB1, ZERO_INIT))
|
|
// point to the bits in the dib passed in
|
|
hpByte = ((PSTR) pNewDib + pNewDib->biSize);
|
|
// copy bits from the dib passed in to the memory just allocated
|
|
memcpy (hpRGB1, hpByte, pNewDib->biSizeImage);
|
|
// the bits pointed to by hpRGB1, and now hpRGB are the original
|
|
// dib bits which must be restored to the dib when we are done.
|
|
// hpRGB1 will change, but hpRGB will always point to the top of
|
|
// memory which makes copying all the bits back to the dib easy.
|
|
hpRGB = hpRGB1;
|
|
// go through all the dib bits searching for RGB(255,255,255)
|
|
// ByteColor is incremented by 3 for the RGB triples
|
|
// hpByte points to the bits in the dib
|
|
// This process builds a mask by setting the RGB transparent
|
|
// color to white and all else to black
|
|
for (ByteColor = 0; (ByteColor < pNewDib->biSizeImage);
|
|
ByteColor = ByteColor + 3,hpByte++ ){
|
|
// if first byte in RGB triple is 255 carry on, else fail
|
|
if (*hpByte == (uchar)255){
|
|
hpByte++;
|
|
// if second byte is 255
|
|
if (*hpByte==(uchar)255){
|
|
hpByte++;
|
|
//if third byte is 255, RGB triple is (255,255,255)
|
|
if(*hpByte==(uchar)255){
|
|
//set color to white
|
|
*(hpByte-2) = (uchar)255;
|
|
*(hpByte-1) = (uchar)255;
|
|
*hpByte = (uchar)255;
|
|
}else{
|
|
// if it fails, dont search the remaining bytes
|
|
// in the RGB triple, increment hpByte and go on
|
|
// Also set the RGB triple to RGB(0,0,0)
|
|
*(hpByte-2) = 0;
|
|
*(hpByte-1) = 0;
|
|
*hpByte = 0;
|
|
}
|
|
}else{
|
|
hpByte++;
|
|
*(hpByte-2) = 0;
|
|
*(hpByte-1) = 0;
|
|
*hpByte = 0;
|
|
}
|
|
}else{
|
|
hpByte = hpByte + 2;
|
|
*(hpByte-2) = 0;
|
|
*(hpByte-1) = 0;
|
|
*hpByte = 0;
|
|
}
|
|
}
|
|
if (nMode == PAINT_MODE_NORMAL){
|
|
// prepare destination dc by blting the mask just prepared
|
|
transparent = TRUE;
|
|
mode = 1;
|
|
CheckError2(IPScaling(hDC, pNewDib, lrScaledRect, nHScale, nVScale, pAnRotation,
|
|
lrDestPt, pImage, transparent, mode,
|
|
nScaleAlgorithm, pMark, &pgray))
|
|
}
|
|
//hpByte now points to the changed bits in the dib
|
|
hpByte = ((PSTR) pNewDib + pNewDib->biSize);
|
|
// now for every color that is white (from above change)
|
|
// set color to black, else set it to its original color.
|
|
// hpRGB1 points to the original bits in the dib
|
|
for (ByteColor=0; (ByteColor < pNewDib->biSizeImage);
|
|
ByteColor=ByteColor + 3,hpByte++, hpRGB1++ ){
|
|
|
|
if (*hpByte == (uchar)255){
|
|
// make sure pointers to original bits and new bits are in sync
|
|
hpByte++;
|
|
hpRGB1++;
|
|
|
|
if (*hpByte==(uchar)255){
|
|
hpByte++;
|
|
hpRGB1++;
|
|
// if color is white, set to black
|
|
if(*hpByte==(uchar)255){
|
|
*(hpByte-2) = 0;
|
|
*(hpByte-1) = 0;
|
|
*hpByte = 0;
|
|
}else{
|
|
// else set to original color
|
|
*(hpByte-2) = *(hpRGB1-2);
|
|
*(hpByte-1) = *(hpRGB1-1);
|
|
*hpByte = *hpRGB1;
|
|
}
|
|
}else{
|
|
hpByte++;
|
|
hpRGB1++;
|
|
*(hpByte-2) = *(hpRGB1-2);
|
|
*(hpByte-1) = *(hpRGB1-1);
|
|
*hpByte = *hpRGB1;
|
|
}
|
|
}else{
|
|
hpByte = hpByte + 2;
|
|
hpRGB1 = hpRGB1 + 2;
|
|
*(hpByte-2) = *(hpRGB1-2);
|
|
*(hpByte-1) = *(hpRGB1-1);
|
|
*hpByte = *hpRGB1;
|
|
}
|
|
|
|
}
|
|
if (nMode == PAINT_MODE_NORMAL){
|
|
// now blt the source transparently
|
|
transparent = TRUE;
|
|
mode = 2;
|
|
CheckError2(IPScaling (hDC, pNewDib, lrScaledRect, nHScale, nVScale, pAnRotation,
|
|
lrDestPt, pImage, transparent, mode,
|
|
nScaleAlgorithm, pMark, &pgray))
|
|
}
|
|
// set dib bits back to the way they were passed in and free mem
|
|
hpByte = ((PSTR) pNewDib + pNewDib->biSize);
|
|
memcpy (hpByte, hpRGB, pNewDib->biSizeImage);
|
|
hpRGB1 = hpRGB;
|
|
goto Exit;
|
|
}
|
|
// for non 24-bit bitmaps
|
|
// In non 24-bit bitmaps the colors are stored in the palette
|
|
// section of the dib, versus actually in the bits themselves
|
|
|
|
// allocate memory to save the original palette
|
|
CheckError2(AllocateMemory(pNewDib->biClrUsed*4, (PPSTR) &pRGB1, ZERO_INIT))
|
|
|
|
pRGB = (RGBQUAD FAR*)((PSTR) pNewDib + pNewDib->biSize);
|
|
// pRGB points to the palette in the dib passed in, pRGB1
|
|
// saves the colors in the original palette
|
|
for (n=0; n<(int) pNewDib->biClrUsed; n++, pRGB++){
|
|
if ((pRGB->rgbRed == 255) && (pRGB->rgbGreen==255)
|
|
&& (pRGB->rgbBlue==255)){
|
|
// for every color, if color is transparent set it
|
|
// to white, else black (prepare the mask)
|
|
pRGB1[n].rgbRed = pRGB->rgbRed;
|
|
pRGB1[n].rgbGreen = pRGB->rgbGreen;
|
|
pRGB1[n].rgbBlue = pRGB->rgbBlue;
|
|
pRGB->rgbRed = 255;
|
|
pRGB->rgbGreen = 255;
|
|
pRGB->rgbBlue = 255;
|
|
}else{
|
|
pRGB1[n].rgbRed = pRGB->rgbRed;
|
|
pRGB1[n].rgbGreen = pRGB->rgbGreen;
|
|
pRGB1[n].rgbBlue = pRGB->rgbBlue;
|
|
pRGB->rgbRed = 0;
|
|
pRGB->rgbGreen = 0;
|
|
pRGB->rgbBlue = 0;
|
|
}
|
|
}
|
|
if (nMode == PAINT_MODE_NORMAL){
|
|
// prepare destination dc by blting the mask
|
|
transparent = TRUE;
|
|
mode = 1;
|
|
CheckError2(IPScaling (hDC, pNewDib, lrScaledRect, nHScale, nVScale, pAnRotation,
|
|
lrDestPt, pImage, transparent, mode,
|
|
nScaleAlgorithm, pMark, &pgray))
|
|
}
|
|
//now point to the changed palette
|
|
pRGB = (RGBQUAD FAR*)((PSTR) pNewDib + pNewDib->biSize);
|
|
for (n=0; n<(int) pNewDib->biClrUsed; n++, pRGB++){
|
|
// for every color, if color is white change to black
|
|
// else set color to its original state
|
|
if ((pRGB->rgbRed == 255) && (pRGB->rgbGreen==255)
|
|
&& (pRGB->rgbBlue==255)){
|
|
pRGB->rgbRed = 0;
|
|
pRGB->rgbGreen = 0;
|
|
pRGB->rgbBlue = 0;
|
|
}else{
|
|
pRGB->rgbRed = pRGB1[n].rgbRed;
|
|
pRGB->rgbGreen = pRGB1[n].rgbGreen;
|
|
pRGB->rgbBlue = pRGB1[n].rgbBlue;
|
|
}
|
|
}
|
|
if (nMode == PAINT_MODE_NORMAL){
|
|
// now do the transparent blt
|
|
transparent = TRUE;
|
|
mode = 2;
|
|
CheckError2(IPScaling (hDC, pNewDib, lrScaledRect, nHScale, nVScale, pAnRotation, lrDestPt,
|
|
pImage, transparent, mode, nScaleAlgorithm, pMark, &pgray))
|
|
}
|
|
// Restore the original color table
|
|
pRGB = (RGBQUAD FAR*)((PSTR) pNewDib + pNewDib->biSize);
|
|
for (n=0; n<(int) pNewDib->biClrUsed; n++, pRGB++){
|
|
pRGB->rgbRed = pRGB1[n].rgbRed;
|
|
pRGB->rgbGreen = pRGB1[n].rgbGreen;
|
|
pRGB->rgbBlue = pRGB1[n].rgbBlue;
|
|
}
|
|
|
|
Exit:
|
|
if (pgray){
|
|
FreeMemory ((PPSTR) &pgray);
|
|
}
|
|
FreeMemory((PPSTR) &hpRGB1);
|
|
FreeMemory((PPSTR) &pRGB1);
|
|
SetROP2(hDC, nOldROP);
|
|
|
|
return (nStatus);
|
|
|
|
}
|
|
/****************************************************************************
|
|
|
|
FUNCTION: StartOperationBitmap
|
|
|
|
PURPOSE: This routine contains the text code for OiStartOperation.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI StartOperationBitmap(HWND hWnd, PANO_IMAGE pAnoImage,
|
|
LPOIOP_START_OPERATION_STRUCT pStartStruct,
|
|
POINT ptPoint, WPARAM fwKeys, int nFlags,
|
|
PWINDOW pWindow, PIMAGE pImage,
|
|
PMARK pMark, HDC hDC, RECT rClientRect,
|
|
LRECT lrFullsizeClientRect, PBOOL pbDeleteMark,
|
|
PBOOL pbMarkComplete, PBOOL pbRepaint){
|
|
|
|
int nStatus = 0;
|
|
FIO_INFO_CGBW FioInfoCgbw;
|
|
FIO_INFORMATION FioInfo;
|
|
PAN_NAME_STRUCT pAnName;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
LRECT lrFSPoint;
|
|
int fid;
|
|
int localfile, error;
|
|
PSTR pFileName;
|
|
char FileName[256];
|
|
int nHMarkScale;
|
|
int nVMarkScale;
|
|
char szRealFilename[255];
|
|
PSTR pRealFilename = szRealFilename;
|
|
int nPage;
|
|
|
|
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
if (pAnoImage->pFormImage != 0){
|
|
nStatus = Error (DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
}
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_FORM:
|
|
case OIOP_AN_IMAGE:
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
if (!pStartStruct->szString[0]){
|
|
nStatus = Error(DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
pFileName = FileName;
|
|
GetFileName (pFileName, (PSTR) pStartStruct->szString);
|
|
GetPageNumandFileName (pRealFilename, &nPage, pFileName);
|
|
|
|
// see if file exists
|
|
if (fid = IMGFileBinaryOpen(hWnd, pRealFilename,
|
|
OF_EXIST, &localfile, &error)){
|
|
nStatus = Error(DISPLAY_IMAGE_MARK_NAME);
|
|
goto Exit;
|
|
}
|
|
// now allocate a block to save the name of the file
|
|
// (file name as passed in, not just created)
|
|
pAnName = 0;
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiFilNam,
|
|
(PPSTR) &pAnName, strlen(pStartStruct->szString) + 1))
|
|
strcpy(pAnName->name, pStartStruct->szString);
|
|
|
|
// get the size of the image so we can set the bounds
|
|
// attribute in pMark
|
|
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
|
|
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
|
|
|
|
FioInfo.filename = pRealFilename;
|
|
FioInfo.page_number = 1;
|
|
FioInfoCgbw.palette_entries = 0;
|
|
FioInfoCgbw.lppalette_table = NULL;
|
|
CheckError2(IMGFileGetInfo(NULL, hWnd, &FioInfo, &FioInfoCgbw, 0))
|
|
// if it is a form type then both base image and form mark must
|
|
// be b & w
|
|
if (((int) pMark->Attributes.uType == OIOP_AN_FORM) &&
|
|
((FioInfoCgbw.image_type != ITYPE_BI_LEVEL) ||
|
|
(pImage->pImg->nType != ITYPE_BI_LEVEL))){
|
|
nStatus = Error (DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
|
|
// Convert pt where image is to be placed to fullsize coords
|
|
lrFSPoint.left = ptPoint.x;
|
|
lrFSPoint.top = ptPoint.y;
|
|
lrFSPoint.right = 0;
|
|
lrFSPoint.bottom = 0;
|
|
ConvertRect(pWindow, &lrFSPoint, CONV_WINDOW_TO_FULLSIZE);
|
|
|
|
nHMarkScale = ((pImage->nHRes * 1000)/ FioInfo.horizontal_dpi);
|
|
nVMarkScale = ((pImage->nVRes * 1000)/ FioInfo.vertical_dpi);
|
|
// Set the dimensions of the image in fullsize
|
|
pMark->Attributes.lrBounds.left = lrFSPoint.left;
|
|
pMark->Attributes.lrBounds.top = lrFSPoint.top;
|
|
pMark->Attributes.lrBounds.right = lrFSPoint.left + (((ulong)FioInfo.horizontal_pixels
|
|
* nHMarkScale)/1000);
|
|
pMark->Attributes.lrBounds.bottom = lrFSPoint.top + (((ulong)FioInfo.vertical_pixels
|
|
* nVMarkScale)/1000);
|
|
// Create the block which will contain rotation info
|
|
// and resolution info
|
|
pAnRotation = 0;
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiAnoDat,
|
|
(PPSTR) &pAnRotation, sizeof (AN_NEW_ROTATE_STRUCT)))
|
|
// Default rotation info to the original image condition
|
|
pAnRotation->rotation = 1;
|
|
pAnRotation->scale = 1000;
|
|
pAnRotation->bFormMark = FALSE;
|
|
pAnRotation->bClipboardOp = FALSE;
|
|
// Resolution info
|
|
pAnRotation->nHRes = FioInfo.horizontal_dpi;
|
|
pAnRotation->nVRes = FioInfo.vertical_dpi;
|
|
pAnRotation->nOrigHRes = FioInfo.horizontal_dpi;
|
|
pAnRotation->nOrigVRes = FioInfo.vertical_dpi;
|
|
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
CheckError2(CacheFile (hWnd, pRealFilename, nPage, &pAnoImage->pFormImage))
|
|
pAnoImage->pFormImage->nLockCount++;
|
|
pAnoImage->pFormMark = pMark;
|
|
pAnoImage->nBPFValidLines = 0;
|
|
pAnoImage->pBasePlusFormImg = 0;
|
|
// *pbMarkComplete = TRUE;
|
|
// *pbRepaint = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
if (nStatus){
|
|
*pbDeleteMark = TRUE;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: ContinueOperationBitmap
|
|
|
|
PURPOSE: This routine contains the text code for OIContinueOperation.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI ContinueOperationBitmap(HWND hWnd, POINT ptPoint, int nFlags,
|
|
PWINDOW pWindow, PIMAGE pImage, PMARK pMark,
|
|
HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect){
|
|
|
|
int nStatus = 0;
|
|
int hoffset, voffset;
|
|
LRECT lrFSptRect;
|
|
int nHScale;
|
|
int nVScale;
|
|
|
|
|
|
CheckError2(TranslateScale(pWindow->nScale, pImage->nHRes, pImage->nVRes,
|
|
&nHScale, &nVScale))
|
|
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_IMAGE:
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
case OIOP_AN_FORM:
|
|
// this xor will erase the present image rect
|
|
CheckError2(PaintAnnotation(hWnd, hDC, pWindow, pImage, pMark,
|
|
rClientRect, lrFullsizeClientRect, PAINT_MODE_DRAG, pWindow->nScale,
|
|
nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, 0, DONT_USE_BI_LEVEL_DITHERING,
|
|
DONT_FORCE_OPAQUE_RECTANGLES))
|
|
SetLRect (lrFSptRect, ptPoint.x, ptPoint.y, 0, 0);
|
|
ConvertRect(pWindow, &lrFSptRect, CONV_WINDOW_TO_FULLSIZE);
|
|
|
|
// calculate image offset to new position being dragged to
|
|
hoffset = (int)(lrFSptRect.left - pMark->Attributes.lrBounds.left);
|
|
voffset = (int)(lrFSptRect.top - pMark->Attributes.lrBounds.top);
|
|
// npdate the bounds of the image to the new position
|
|
pMark->Attributes.lrBounds.left =
|
|
pMark->Attributes.lrBounds.left + hoffset;
|
|
pMark->Attributes.lrBounds.right =
|
|
pMark->Attributes.lrBounds.right + hoffset;
|
|
pMark->Attributes.lrBounds.top =
|
|
pMark->Attributes.lrBounds.top + voffset;
|
|
pMark->Attributes.lrBounds.bottom =
|
|
pMark->Attributes.lrBounds.bottom + voffset;
|
|
// this xor will draw the new rect at the new location
|
|
CheckError2(PaintAnnotation(hWnd, hDC, pWindow, pImage, pMark,
|
|
rClientRect, lrFullsizeClientRect, PAINT_MODE_DRAG, pWindow->nScale,
|
|
nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, 0, DONT_USE_BI_LEVEL_DITHERING,
|
|
DONT_FORCE_OPAQUE_RECTANGLES))
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: EndOperationBitmap
|
|
|
|
PURPOSE: This routine contains the image code for OIEndOperation.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI EndOperationBitmap(HWND hWnd, PWINDOW pWindow,
|
|
PIMAGE pImage, PMARK pMark, HDC hDC,
|
|
RECT rClientRect, LRECT lrFullsizeClientRect,
|
|
PBOOL pbDeleteMark, PBOOL pbRepaint){
|
|
|
|
int nStatus = 0;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation = 0;
|
|
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_IMAGE:
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
case OIOP_AN_FORM:
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
// repaint entire window now that we know where the mark
|
|
// needs to be redrawn
|
|
*pbRepaint = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: RotateImage
|
|
|
|
PURPOSE: This routine contains the code for rotating the form image
|
|
|
|
****************************************************************************/
|
|
int WINAPI RotateImage (PMARK pMark, PIMAGE pFormImage, int nRotation){
|
|
|
|
int nStatus;
|
|
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
int tempres;
|
|
PIMG pTempImg = 0;
|
|
|
|
|
|
pAnRotation = 0;
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
if (pAnRotation == 0){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
|
|
switch (nRotation){
|
|
// no rotation needed
|
|
case 1:
|
|
break;
|
|
//rotate right
|
|
case 2:
|
|
CheckError2(CreateAnyImgBuf(&pTempImg, pFormImage->nHeight,
|
|
pFormImage->nWidth, pFormImage->pImg->nType))
|
|
CheckError2(RotateRight90(pFormImage->pImg, pTempImg,
|
|
pFormImage->nWidth, pFormImage->nHeight))
|
|
|
|
FreeImgBuf(&pFormImage->pImg);
|
|
MoveImage(&pTempImg, &pFormImage->pImg);
|
|
// npdate resolution info
|
|
tempres = pAnRotation->nVRes;
|
|
pAnRotation->nVRes = pAnRotation->nHRes;
|
|
pAnRotation->nHRes = tempres;
|
|
tempres = pFormImage->nVRes;
|
|
pFormImage->nVRes = pFormImage->nHRes;
|
|
pFormImage->nHRes = tempres;
|
|
pFormImage->nWidth = pFormImage->pImg->nWidth;
|
|
pFormImage->nHeight = pFormImage->pImg->nHeight;
|
|
break;
|
|
|
|
// rotate 180
|
|
case 3: //OD_FLIP:
|
|
CheckError2(Flip(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
break;
|
|
//rotate left
|
|
case 4:
|
|
CheckError2(CreateAnyImgBuf(&pTempImg, pFormImage->nHeight,
|
|
pFormImage->nWidth, pFormImage->pImg->nType))
|
|
CheckError2(RotateRight270(pFormImage->pImg, pTempImg,
|
|
pFormImage->nWidth, pFormImage->nHeight))
|
|
|
|
FreeImgBuf(&pFormImage->pImg);
|
|
MoveImage(&pTempImg, &pFormImage->pImg);
|
|
// npdate resolution info
|
|
tempres = pAnRotation->nVRes;
|
|
pAnRotation->nVRes = pAnRotation->nHRes;
|
|
pAnRotation->nHRes = tempres;
|
|
tempres = pFormImage->nVRes;
|
|
pFormImage->nVRes = pFormImage->nHRes;
|
|
pFormImage->nHRes = tempres;
|
|
pFormImage->nWidth = pFormImage->pImg->nWidth;
|
|
pFormImage->nHeight = pFormImage->pImg->nHeight;
|
|
break;
|
|
// vertical mirror
|
|
case 5:
|
|
CheckError2(VerticalMirror(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
break;
|
|
// vertical mirror and rotate right
|
|
case 6:
|
|
CheckError2(VerticalMirror(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
CheckError2(CreateAnyImgBuf(&pTempImg, pFormImage->nHeight,
|
|
pFormImage->nWidth, pFormImage->pImg->nType))
|
|
CheckError2(RotateRight90(pFormImage->pImg, pTempImg,
|
|
pFormImage->nWidth, pFormImage->nHeight))
|
|
|
|
FreeImgBuf(&pFormImage->pImg);
|
|
MoveImage(&pTempImg, &pFormImage->pImg);
|
|
// npdate resolution info
|
|
tempres = pAnRotation->nVRes;
|
|
pAnRotation->nVRes = pAnRotation->nHRes;
|
|
pAnRotation->nHRes = tempres;
|
|
tempres = pFormImage->nVRes;
|
|
pFormImage->nVRes = pFormImage->nHRes;
|
|
pFormImage->nHRes = tempres;
|
|
pFormImage->nWidth = pFormImage->pImg->nWidth;
|
|
pFormImage->nHeight = pFormImage->pImg->nHeight;
|
|
break;
|
|
//vertical mirror and rotate 180
|
|
case 7:
|
|
CheckError2(VerticalMirror(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
CheckError2(Flip(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
break;
|
|
//vertical mirror and rotate left
|
|
case 8:
|
|
CheckError2(VerticalMirror(pFormImage->pImg, pFormImage->nWidth, pFormImage->nHeight))
|
|
CheckError2(CreateAnyImgBuf(&pTempImg, pFormImage->nHeight,
|
|
pFormImage->nWidth, pFormImage->pImg->nType))
|
|
CheckError2(RotateRight270(pFormImage->pImg, pTempImg,
|
|
pFormImage->nWidth, pFormImage->nHeight))
|
|
|
|
FreeImgBuf(&pFormImage->pImg);
|
|
MoveImage(&pTempImg, &pFormImage->pImg);
|
|
// npdate resolution info
|
|
tempres = pAnRotation->nVRes;
|
|
pAnRotation->nVRes = pAnRotation->nHRes;
|
|
pAnRotation->nHRes = tempres;
|
|
tempres = pFormImage->nVRes;
|
|
pFormImage->nVRes = pFormImage->nHRes;
|
|
pFormImage->nHRes = tempres;
|
|
pFormImage->nWidth = pFormImage->pImg->nWidth;
|
|
pFormImage->nHeight = pFormImage->pImg->nHeight;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
FUNCTION: OiImageToDib
|
|
|
|
PURPOSE: Converts an Open/image image to a DIB. The filename of
|
|
the O/i image is passed in, and a handle to the DIB returned
|
|
|
|
*******************************************************************************/
|
|
|
|
int WINAPI OiImageToDib(HWND hWnd, PSTR pFilename, PBITMAPINFOHEADER *ppDib){
|
|
|
|
int nStatus;
|
|
|
|
PIMAGE pImage=0;
|
|
RECT rRect;
|
|
int nPage=1;
|
|
char szRealFilename[255];
|
|
PSTR pRealFilename = szRealFilename;
|
|
|
|
GetPageNumandFileName (pRealFilename, &nPage, pFilename);
|
|
CheckError2(CacheFile(hWnd, pRealFilename, nPage, &pImage))
|
|
CheckError2(CacheRead(hWnd, pImage, pImage->nHeight))
|
|
SetRect (&rRect, 0, 0, (int) pImage->nWidth, (int) pImage->nHeight);
|
|
CheckError2(IPtoDIB (pImage, pImage->pImg, ppDib, rRect))
|
|
|
|
|
|
Exit:
|
|
return (nStatus);
|
|
|
|
}
|
|
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: PaintAnnotationBitmap
|
|
|
|
PURPOSE: This routine Paints an annotation on an hDC.
|
|
This routine contains the text code for PaintAnnotation.
|
|
|
|
INPUTS: nMode - PAINT_MODE_XOR - Draw the mark XORed with white.
|
|
PAINT_MODE_DRAG - Draw the mark for dragging purposes.
|
|
PAINT_MODE_NORMAL - Draw the mark as it normally appears.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI PaintAnnotationBitmap(HWND hWnd, HDC hDC, PWINDOW pWindow,
|
|
PIMAGE pImage, PMARK pMark, RECT rRepaintRect,
|
|
LRECT lrFullsizeRepaintRect, int nMode, int nScale,
|
|
int nHScale, int nVScale, long lHOffset, long lVOffset,
|
|
int nFlags){
|
|
|
|
int nStatus = 0;
|
|
PDISPLAY pDisplay;
|
|
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
PBITMAPINFOHEADER pDisplayDib;
|
|
LRECT lrScaledRect, lrDestPt, lrFSRect, lrWindowMark;
|
|
PAN_IMAGE_STRUCT pAnImage = 0;
|
|
PAN_IMAGE_STRUCT pDisplayAnImage = 0;
|
|
PAN_NAME_STRUCT pAnName = 0;
|
|
PSTR pFileName;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation = 0;
|
|
int nRopCode;
|
|
int nOldROP;
|
|
HBRUSH hOldBrush;
|
|
BOOL bBrushSelected = FALSE;
|
|
BOOL bPenSelected = FALSE;
|
|
HPEN hOldPen;
|
|
BOOL transparent;
|
|
int mode;
|
|
PPSTR ppgray=0;
|
|
int fid;
|
|
int localfile, error;
|
|
char FileName[256];
|
|
PARM_SCALE_ALGORITHM_STRUCT ScaleAlgStruct;
|
|
int nPage=1;
|
|
char szRealFilename[255];
|
|
PSTR pRealFilename = szRealFilename;
|
|
PSTR plrMarkBounds=0 ;
|
|
|
|
|
|
|
|
pDisplay = pWindow->pDisplay;
|
|
|
|
switch (nMode){
|
|
case PAINT_MODE_DRAG:
|
|
case PAINT_MODE_XOR:
|
|
nRopCode = R2_XORPEN;
|
|
break;
|
|
|
|
case PAINT_MODE_NORMAL:
|
|
nRopCode = R2_COPYPEN;
|
|
break;
|
|
}
|
|
nOldROP = SetROP2(hDC, nRopCode);
|
|
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_IMAGE:
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
case OIOP_AN_FORM:
|
|
pAnName = 0;
|
|
pAnImage = 0;
|
|
pAnRotation = 0;
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiFilNam, (PPSTR) &pAnName))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage))
|
|
CheckError2(GetAMarkNamedBlock(pMark, "MarkBnds", (PPSTR) &plrMarkBounds))
|
|
|
|
//save these bounds, if they change the next time around, it means the mark needs
|
|
// to be resized
|
|
if (!plrMarkBounds) {
|
|
CheckError2(AllocateMemory(sizeof(LRECT), &plrMarkBounds, ZERO_INIT))
|
|
((LRECT *)plrMarkBounds)->left = pMark->Attributes.lrBounds.left ;
|
|
((LRECT *)plrMarkBounds)->top = pMark->Attributes.lrBounds.top ;
|
|
((LRECT *)plrMarkBounds)->right = pMark->Attributes.lrBounds.right ;
|
|
((LRECT *)plrMarkBounds)->bottom = pMark->Attributes.lrBounds.bottom ;
|
|
CheckError2(AddAMarkNamedBlock(pMark, "MarkBnds",
|
|
(PPSTR) &plrMarkBounds, sizeof (LRECT)))
|
|
}
|
|
|
|
// if there is no image and no name, what can be done???
|
|
if ((!pAnImage) && (!pAnName) || (!pAnRotation)){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
|
|
// if there is a name but no image, create the dib
|
|
if (!pAnImage){
|
|
pFileName = FileName;
|
|
GetFileName (pFileName, (PSTR) pAnName->name);
|
|
GetPageNumandFileName (pRealFilename, &nPage, pFileName);
|
|
|
|
// see if file exists
|
|
if (fid = IMGFileBinaryOpen(hWnd, pRealFilename, OF_EXIST, &localfile, &error)){
|
|
nStatus = Error(DISPLAY_IMAGE_MARK_NAME);
|
|
goto Exit;
|
|
}
|
|
CheckError2(OiImageToDib (hWnd, pFileName, &pDib))
|
|
pAnImage = 0;
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiDIB,
|
|
(PPSTR) &pAnImage, sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed*4) + (pDib->biSizeImage)))
|
|
memcpy (pAnImage->dibInfo, pDib,
|
|
sizeof(BITMAPINFOHEADER) + (pDib->biClrUsed*4) + (pDib->biSizeImage));
|
|
}
|
|
|
|
// now we must scale the coords obtained above, which were
|
|
// in fullsize
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE_BY_REFERENCE){
|
|
// for image by reference, the final scale must also
|
|
// include the initial scale for the image, saved in
|
|
// pAnRotation (ie, an image saved at 50% will have
|
|
// the scale info for the ref. image at 50%)
|
|
nScale = (pAnRotation->scale * nScale) / 1000;
|
|
// tempscale = (pAnRotation->scale * nScale) / 1000;
|
|
// nScale = tempscale;
|
|
}else if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE){
|
|
// for embedded image no such problems, scale is
|
|
// whatever the display scale is
|
|
// nScale = nScale;
|
|
}
|
|
|
|
ScaleAlgStruct.uImageFlags = pImage->nRWDataType;
|
|
|
|
if ((((nScale * pImage->nHRes) / pAnRotation->nHRes) > 1000 ||
|
|
((nScale * pImage->nVRes) / pAnRotation->nVRes) > 1000) ||
|
|
(((PBITMAPINFOHEADER) pAnImage)->biBitCount != 1)){
|
|
ScaleAlgStruct.uScaleAlgorithm = OI_SCALE_ALG_NORMAL;
|
|
// }else if (nStatus = IMGGetParmsCgbw (hWnd, PARM_SCALE_ALGORITHM,
|
|
// &ScaleAlgStruct, PARM_IMAGE | PARM_NO_DEFAULT)){
|
|
// goto Exit;
|
|
// }
|
|
}else{
|
|
ScaleAlgStruct.uScaleAlgorithm = pDisplay->nCurrentScaleAlgorithm ;
|
|
}
|
|
if (ScaleAlgStruct.uScaleAlgorithm == OI_SCALE_ALG_AVERAGE_TO_GRAY8){
|
|
ScaleAlgStruct.uScaleAlgorithm = OI_SCALE_ALG_AVERAGE_TO_GRAY7;
|
|
}
|
|
|
|
// if the base image scale algorithm has changed then throw the display
|
|
// dib away
|
|
if (pDisplayAnImage && (pAnRotation->nReserved[0] != (int)ScaleAlgStruct.uScaleAlgorithm)){
|
|
CheckError2(DeleteAMarkNamedBlock (pMark, szOiZDpDIB))
|
|
pDisplayAnImage = 0;
|
|
}
|
|
if (pDisplayAnImage){
|
|
pDisplayDib = (PBITMAPINFOHEADER) pDisplayAnImage;
|
|
}
|
|
if ((!pDisplayAnImage || pAnRotation->nHRes != pImage->nHRes
|
|
|| pAnRotation->nVRes != pImage->nVRes
|
|
|| ((LRECT *)plrMarkBounds)->left != pMark->Attributes.lrBounds.left
|
|
|| ((LRECT *)plrMarkBounds)->top != pMark->Attributes.lrBounds.top
|
|
|| ((LRECT *)plrMarkBounds)->right != pMark->Attributes.lrBounds.right
|
|
|| ((LRECT *)plrMarkBounds)->bottom != pMark->Attributes.lrBounds.bottom)
|
|
&& (int) pMark->Attributes.uType != OIOP_AN_FORM){
|
|
CheckError2(ConvResolutionAnoBitmap(hWnd, pMark, pAnRotation->rotation,
|
|
ScaleAlgStruct.uScaleAlgorithm))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage))
|
|
pDisplayDib = (PBITMAPINFOHEADER) pDisplayAnImage;
|
|
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
}
|
|
// save the base image scale algorithm so that if it changes, the display
|
|
// dib can be thrown away and regenerated
|
|
pAnRotation->nReserved[0] = (int)ScaleAlgStruct.uScaleAlgorithm;
|
|
// save the current image bounds
|
|
((LRECT *)plrMarkBounds)->left = pMark->Attributes.lrBounds.left ;
|
|
((LRECT *)plrMarkBounds)->top = pMark->Attributes.lrBounds.top ;
|
|
((LRECT *)plrMarkBounds)->right = pMark->Attributes.lrBounds.right ;
|
|
((LRECT *)plrMarkBounds)->bottom = pMark->Attributes.lrBounds.bottom ;
|
|
|
|
if (nFlags != OIAN_CLIPBOARD_OPERATION){
|
|
// clip the image to the repaint rect
|
|
if (pMark->Attributes.lrBounds.left <= lrFullsizeRepaintRect.left){
|
|
lrFSRect.left = lrFullsizeRepaintRect.left;
|
|
}else{
|
|
lrFSRect.left = pMark->Attributes.lrBounds.left;
|
|
}if (pMark->Attributes.lrBounds.right >= lrFullsizeRepaintRect.right){
|
|
lrFSRect.right = lrFullsizeRepaintRect.right;
|
|
}else{
|
|
lrFSRect.right = pMark->Attributes.lrBounds.right;
|
|
}if (pMark->Attributes.lrBounds.top <= lrFullsizeRepaintRect.top){
|
|
lrFSRect.top = lrFullsizeRepaintRect.top;
|
|
}else{
|
|
lrFSRect.top = pMark->Attributes.lrBounds.top;
|
|
}if (pMark->Attributes.lrBounds.bottom >=
|
|
lrFullsizeRepaintRect.bottom){
|
|
lrFSRect.bottom = lrFullsizeRepaintRect.bottom;
|
|
}else{
|
|
lrFSRect.bottom = pMark->Attributes.lrBounds.bottom;
|
|
}
|
|
|
|
// if repaint rect is outside base image bounds, then
|
|
// do nothing
|
|
if ((lrFSRect.top > pImage->nHeight) ||
|
|
(lrFSRect.left > pImage->nWidth)){
|
|
goto Exit;
|
|
}
|
|
// clip the image to the base image
|
|
if (lrFSRect.right > pImage->nWidth){
|
|
lrFSRect.right = pImage->nWidth;
|
|
}if (lrFSRect.bottom > pImage->nHeight){
|
|
lrFSRect.bottom = pImage->nHeight;
|
|
}
|
|
}else{
|
|
CopyRect (lrFSRect, pMark->Attributes.lrBounds);
|
|
}
|
|
// coords of the portion of the image to be displayed
|
|
// relative to the entire image mark. Needed by ippack
|
|
// to get a portion of the image
|
|
lrFSRect.bottom = lmax (0, lrFSRect.bottom - pMark->Attributes.lrBounds.top);
|
|
lrFSRect.right = lmax (0, lrFSRect.right - pMark->Attributes.lrBounds.left);
|
|
lrFSRect.left = lmax (0, lrFSRect.left - pMark->Attributes.lrBounds.left);
|
|
lrFSRect.top = lmax (0, lrFSRect.top - pMark->Attributes.lrBounds.top);
|
|
|
|
// scale the image rect
|
|
SetLRect (lrScaledRect, lrFSRect.left, lrFSRect.top, lrFSRect.right,
|
|
lrFSRect.bottom);
|
|
ConvertRect2(&lrScaledRect, CONV_FULLSIZE_TO_SCALED,
|
|
nHScale, nVScale, lHOffset, lVOffset);
|
|
// get the npper left corner of the image relative to
|
|
// the DC, needed by BitBlt as X and Y
|
|
SetLRect (lrWindowMark, pMark->Attributes.lrBounds.left,
|
|
pMark->Attributes.lrBounds.top, 0, 0);
|
|
ConvertRect2(&lrWindowMark, CONV_FULLSIZE_TO_WINDOW,
|
|
nHScale, nVScale, lHOffset, lVOffset);
|
|
lrDestPt.top = lmax (lrWindowMark.top, rRepaintRect.top);
|
|
lrDestPt.left = lmax (lrWindowMark.left, rRepaintRect.left);
|
|
|
|
|
|
if (!pMark->Attributes.bTransparent ||
|
|
((int) pMark->Attributes.uType == OIOP_AN_FORM)){
|
|
if ((nMode == PAINT_MODE_DRAG) || (nMode == PAINT_MODE_XOR)){
|
|
// draw a grey rect while image is being dragged
|
|
hOldPen = SelectObject(hDC, GetStockObject(NULL_PEN));
|
|
hOldBrush = SelectObject(hDC, GetStockObject(GRAY_BRUSH));
|
|
bBrushSelected = TRUE;
|
|
bPenSelected = TRUE;
|
|
Rectangle (hDC, (int)lrDestPt.left ,
|
|
(int)lrDestPt.top, (int)lrDestPt.left +
|
|
(int)(lrScaledRect.right-lrScaledRect.left),
|
|
(int)lrDestPt.top +
|
|
(int)(lrScaledRect.bottom-lrScaledRect.top));
|
|
}else if (nMode == PAINT_MODE_NORMAL){
|
|
transparent = FALSE;
|
|
mode = 0;
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
goto Exit;
|
|
}
|
|
// scale the dib and blt it to the DC
|
|
CheckError2(IPScaling (hDC, pDisplayDib, lrScaledRect,
|
|
nHScale, nVScale, pAnRotation,lrDestPt, pImage,
|
|
transparent, mode, ScaleAlgStruct.uScaleAlgorithm,
|
|
pMark, ppgray))
|
|
}
|
|
}else if (pMark->Attributes.bTransparent){
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
goto Exit;
|
|
}
|
|
// do the transparent for pure white stuff
|
|
CheckError2(BitsTransparent(hDC, pDisplayDib,
|
|
lrScaledRect, pAnRotation, lrDestPt, nMode, pImage,
|
|
nHScale, nVScale, ScaleAlgStruct.uScaleAlgorithm, pMark))
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
FreeMemory((PPSTR) &pDib);
|
|
|
|
if (bBrushSelected){
|
|
SelectObject(hDC, hOldBrush);
|
|
}
|
|
if (bPenSelected){
|
|
SelectObject (hDC, hOldPen);
|
|
}
|
|
SetROP2(hDC, nOldROP);
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: OrientAnnotationBitmap
|
|
|
|
PURPOSE: This routine orients the annotation.
|
|
This routine contains the text code for OrientAnnotations.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI OrientAnnotationBitmap(HWND hWnd, PWINDOW pWindow,
|
|
PIMAGE pImage, int nOrientation, PMARK pMark){
|
|
|
|
int nStatus = 0;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
long templeft, temptop, tempright;
|
|
|
|
pAnRotation = 0;
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
|
|
if (!pAnRotation){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE ||
|
|
(int) pMark->Attributes.uType == OIOP_AN_IMAGE_BY_REFERENCE ||
|
|
(int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
switch (nOrientation){// this saves the new rotation state of the
|
|
// image. A horizontal mirror is saved as
|
|
// a vertical mirror, then a rotate 180
|
|
// This info only needed for ref.images
|
|
//1=original, 2=rot.right, 3=flip, 4=rot.left, 5=vert.mirror
|
|
//6=vert.mirr,rot.right, 7=vert.mirror,flip, 8=vert.mirror,rot.left
|
|
case OD_ROTRIGHT:
|
|
switch (pAnRotation->rotation){
|
|
case 1: pAnRotation->rotation = 2; break;
|
|
case 2: pAnRotation->rotation = 3; break;
|
|
case 3: pAnRotation->rotation = 4; break;
|
|
case 4: pAnRotation->rotation = 1; break;
|
|
case 5: pAnRotation->rotation = 6; break;
|
|
case 6: pAnRotation->rotation = 7; break;
|
|
case 7: pAnRotation->rotation = 8; break;
|
|
case 8: pAnRotation->rotation = 5; break;
|
|
}
|
|
break;
|
|
case OD_ROTLEFT:
|
|
switch (pAnRotation->rotation){
|
|
case 1: pAnRotation->rotation = 4; break;
|
|
case 2: pAnRotation->rotation = 1; break;
|
|
case 3: pAnRotation->rotation = 2; break;
|
|
case 4: pAnRotation->rotation = 3; break;
|
|
case 5: pAnRotation->rotation = 8; break;
|
|
case 6: pAnRotation->rotation = 5; break;
|
|
case 7: pAnRotation->rotation = 6; break;
|
|
case 8: pAnRotation->rotation = 7; break;
|
|
}
|
|
break;
|
|
case OD_FLIP:
|
|
switch (pAnRotation->rotation){
|
|
case 1: pAnRotation->rotation = 3; break;
|
|
case 2: pAnRotation->rotation = 4; break;
|
|
case 3: pAnRotation->rotation = 1; break;
|
|
case 4: pAnRotation->rotation = 2; break;
|
|
case 5: pAnRotation->rotation = 7; break;
|
|
case 6: pAnRotation->rotation = 8; break;
|
|
case 7: pAnRotation->rotation = 5; break;
|
|
case 8: pAnRotation->rotation = 6; break;
|
|
}
|
|
break;
|
|
case OD_HMIRROR:
|
|
switch (pAnRotation->rotation){
|
|
case 1: pAnRotation->rotation = 7; break;
|
|
case 2: pAnRotation->rotation = 6; break;
|
|
case 3: pAnRotation->rotation = 5; break;
|
|
case 4: pAnRotation->rotation = 8; break;
|
|
case 5: pAnRotation->rotation = 3; break;
|
|
case 6: pAnRotation->rotation = 2; break;
|
|
case 7: pAnRotation->rotation = 1; break;
|
|
case 8: pAnRotation->rotation = 4; break;
|
|
}
|
|
break;
|
|
case OD_VMIRROR:
|
|
switch (pAnRotation->rotation){
|
|
case 1: pAnRotation->rotation = 5; break;
|
|
case 2: pAnRotation->rotation = 8; break;
|
|
case 3: pAnRotation->rotation = 7; break;
|
|
case 4: pAnRotation->rotation = 6; break;
|
|
case 5: pAnRotation->rotation = 1; break;
|
|
case 6: pAnRotation->rotation = 4; break;
|
|
case 7: pAnRotation->rotation = 3; break;
|
|
case 8: pAnRotation->rotation = 2; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE
|
|
|| (int) pMark->Attributes.uType == OIOP_AN_IMAGE_BY_REFERENCE){
|
|
switch (nOrientation){
|
|
case OD_FLIP:
|
|
// npdate the bounds of the image in pMark
|
|
templeft = pMark->Attributes.lrBounds.left;
|
|
temptop = pMark->Attributes.lrBounds.top;
|
|
pMark->Attributes.lrBounds.left
|
|
= pImage->nWidth - pMark->Attributes.lrBounds.right;
|
|
pMark->Attributes.lrBounds.top
|
|
= pImage->nHeight - pMark->Attributes.lrBounds.bottom;
|
|
pMark->Attributes.lrBounds.right = pImage->nWidth - templeft;
|
|
pMark->Attributes.lrBounds.bottom = pImage->nHeight - temptop;
|
|
break;
|
|
case OD_HMIRROR:
|
|
templeft = pMark->Attributes.lrBounds.left;
|
|
temptop = pMark->Attributes.lrBounds.top;
|
|
pMark->Attributes.lrBounds.top
|
|
= pImage->nHeight - pMark->Attributes.lrBounds.bottom;
|
|
pMark->Attributes.lrBounds.bottom = pImage->nHeight - temptop;
|
|
break;
|
|
case OD_VMIRROR:
|
|
templeft = pMark->Attributes.lrBounds.left;
|
|
temptop = pMark->Attributes.lrBounds.top;
|
|
pMark->Attributes.lrBounds.left
|
|
= pImage->nWidth - pMark->Attributes.lrBounds.right;
|
|
pMark->Attributes.lrBounds.right = pImage->nWidth - templeft;
|
|
break;
|
|
case OD_ROTRIGHT:
|
|
case OD_ROTLEFT:
|
|
if (nOrientation == OD_ROTRIGHT){
|
|
tempright = pMark->Attributes.lrBounds.right;
|
|
temptop = pMark->Attributes.lrBounds.top;
|
|
templeft = pMark->Attributes.lrBounds.left;
|
|
|
|
pMark->Attributes.lrBounds.left
|
|
= pImage->nHeight - pMark->Attributes.lrBounds.bottom;
|
|
pMark->Attributes.lrBounds.top = templeft;
|
|
pMark->Attributes.lrBounds.right
|
|
= pImage->nHeight - temptop;
|
|
pMark->Attributes.lrBounds.bottom = tempright;
|
|
|
|
}else{ // OD_ROTLEFT
|
|
templeft = pMark->Attributes.lrBounds.left;
|
|
pMark->Attributes.lrBounds.left
|
|
= pMark->Attributes.lrBounds.top;
|
|
pMark->Attributes.lrBounds.top
|
|
= pImage->nWidth - pMark->Attributes.lrBounds.right;
|
|
pMark->Attributes.lrBounds.right
|
|
= pMark->Attributes.lrBounds.bottom;
|
|
pMark->Attributes.lrBounds.bottom = pImage->nWidth - templeft;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
CheckError2(DeleteAMarkNamedBlock (pMark, szOiZDpDIB))
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: ScaleAnnotationImage
|
|
|
|
PURPOSE: This scales an annotation down to the size specified in the
|
|
pSaveEx structure.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI ScaleAnnotationImage(HWND hWnd, PMARK pMark, int nHScale, int nVScale,
|
|
int nScaleAlgorithm){
|
|
|
|
int nStatus = 0;
|
|
HDC hlocalDC;
|
|
PAN_IMAGE_STRUCT pAnImage=0;
|
|
PBITMAPINFOHEADER pDib;
|
|
LRECT lrDestPt;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation=0;
|
|
IMAGE Image;
|
|
PPSTR ppgray=0;
|
|
int temp;
|
|
ulong nScale;
|
|
LRECT lrDibBounds;
|
|
PAN_IMAGE_STRUCT pDisplayAnImage = 0;
|
|
|
|
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
if (!pAnRotation){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage))
|
|
|
|
// since this routine is called before a save, for image by ref. npdate
|
|
// the bounds but don't scale the dib since it will be thrown away
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE_BY_REFERENCE
|
|
|| (int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
nScale = (nHScale * pAnRotation->scale)/
|
|
1000;
|
|
pAnRotation->scale = nScale;
|
|
pMark->Attributes.lrBounds.left = ( pMark->Attributes.lrBounds.left
|
|
* nHScale) / 1000;
|
|
pMark->Attributes.lrBounds.right = ( pMark->Attributes.lrBounds.right
|
|
* nHScale) / 1000;
|
|
pMark->Attributes.lrBounds.top = ( pMark->Attributes.lrBounds.top
|
|
* nVScale) / 1000;
|
|
pMark->Attributes.lrBounds.bottom = ( pMark->Attributes.lrBounds.bottom
|
|
* nVScale) / 1000;
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
if ((int) pMark->Attributes.uType != OIOP_AN_IMAGE)
|
|
goto Exit; // this routine should only be called for embedded images
|
|
// or image by reference
|
|
|
|
pAnImage = 0;
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage))
|
|
if (!pAnImage){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit; // must have dib bits to scale
|
|
}
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_IMAGE:
|
|
pDib = (PBITMAPINFOHEADER) pAnImage;
|
|
|
|
pMark->Attributes.lrBounds.left = ( pMark->Attributes.lrBounds.left
|
|
* nHScale) / 1000;
|
|
pMark->Attributes.lrBounds.right = ( pMark->Attributes.lrBounds.right
|
|
* nHScale) / 1000;
|
|
pMark->Attributes.lrBounds.top = ( pMark->Attributes.lrBounds.top
|
|
* nVScale) / 1000;
|
|
pMark->Attributes.lrBounds.bottom = ( pMark->Attributes.lrBounds.bottom
|
|
* nVScale) / 1000;
|
|
if (!(hlocalDC = CreateCompatibleDC (NULL))){
|
|
nStatus = Error (DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
SetLRect (lrDestPt, 0, 0, 0, 0);
|
|
// presently resolution of image is same vertically
|
|
// and horiz due to the way scaleImage works, so
|
|
// account for it
|
|
temp = pAnRotation->nVRes;
|
|
pAnRotation->nVRes = pAnRotation->nHRes;
|
|
// mode is set to 3, so new dib is saved to mark
|
|
SetLRect (lrDibBounds, 0, 0, (int) pDib->biWidth, (int) pDib->biHeight);
|
|
ConvertRect2(&lrDibBounds, CONV_FULLSIZE_TO_SCALED, nHScale,
|
|
nHScale, 0, 0);
|
|
|
|
CheckError2(IPScaling (hlocalDC, pDib, lrDibBounds,
|
|
nHScale, nHScale, pAnRotation, lrDestPt, &Image,
|
|
FALSE, 3, nScaleAlgorithm, pMark, ppgray))
|
|
|
|
pAnRotation->nVRes = temp;
|
|
DeleteDC (hlocalDC);
|
|
/* pMark->Attributes.uLineSize = (( pMark->Attributes.uLineSize
|
|
* pSaveEx->nScaleFactor) / 1000);
|
|
*/
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Exit:
|
|
if (pAnRotation){
|
|
// set resolution back to original, since display dib will be thrown away
|
|
pAnRotation->nHRes = pAnRotation->nOrigHRes;
|
|
pAnRotation->nVRes = pAnRotation->nOrigVRes;
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CanMarkBeScaledImage
|
|
|
|
PURPOSE: This tests an annotation to see if it can be scaled to a
|
|
particular scale factor.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI CanMarkBeScaledImage(HWND hWnd, PMARK pMark, int nScale){
|
|
|
|
DWORD LocalScale;
|
|
int nStatus = 0;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
|
|
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_IMAGE:
|
|
if ((nScale >65000) || (nScale <20)){
|
|
nStatus = Error(DISPLAY_INVALIDSCALE);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
case OIOP_AN_FORM:
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
// make sure for image by ref the final scale (initial image by
|
|
// ref.scale * nScale) is within bounds
|
|
if (!pAnRotation){
|
|
nStatus = Error(DISPLAY_INVALIDSCALE);
|
|
goto Exit;
|
|
}
|
|
LocalScale = (pAnRotation->scale * nScale)/ 1000;
|
|
if ((LocalScale >65000) || (LocalScale <20)){
|
|
nStatus = Error(DISPLAY_INVALIDSCALE);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Exit:
|
|
return (nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: ConvResolutionAnoBitmap
|
|
|
|
PURPOSE: This is called whenever the resolution of the base image is
|
|
being changed. Its purpose is to change the resolution of this
|
|
mark.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI ConvResolutionAnoBitmap(HWND hWnd, PMARK pMark, int nRotation,
|
|
int nScaleAlgorithm){
|
|
|
|
int nStatus = 0;
|
|
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
PBITMAPINFOHEADER pDib;
|
|
PBITMAPINFOHEADER pNewDib;
|
|
IMAGE MarkImage;
|
|
RECT rRect;
|
|
PWINDOW pWindow;
|
|
PANO_IMAGE pAnoImage;
|
|
PIMAGE pImage;
|
|
PAN_IMAGE_STRUCT pAnImage = 0;
|
|
PAN_IMAGE_STRUCT pDisplayAnImage = 0;
|
|
PIMG pTempImg = 0;
|
|
LRECT *plrMarkBounds=0 ;
|
|
|
|
|
|
CheckError2(Init(hWnd, &pWindow, &pAnoImage, FALSE, TRUE))
|
|
pImage = pAnoImage->pBaseImage;
|
|
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage))
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage))
|
|
CheckError2(GetAMarkNamedBlock(pMark, "MarkBnds", (PPSTR) &plrMarkBounds))
|
|
if (!pAnImage){
|
|
Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
pDib = (PBITMAPINFOHEADER) pAnImage;
|
|
|
|
CheckError2(DibToIpNoPal(&MarkImage.pImg, pDib))
|
|
MarkImage.nHeight = (int) (int) pDib->biHeight;
|
|
MarkImage.nWidth = (int) pDib->biWidth;
|
|
|
|
pAnRotation->nHRes = pAnRotation->nOrigHRes;
|
|
pAnRotation->nVRes = pAnRotation->nOrigVRes;
|
|
CheckError2(RotateImage (pMark, &MarkImage, nRotation))
|
|
|
|
SetRect(&rRect, 0, 0, MarkImage.pImg->nWidth, MarkImage.pImg->nHeight);
|
|
CheckError2(ScaleImage(MarkImage.pImg, &pTempImg,
|
|
(int)(((pMark->Attributes.lrBounds.right - pMark->Attributes.lrBounds.left) * 1000L) /
|
|
MarkImage.pImg->nWidth),
|
|
(int)(((pMark->Attributes.lrBounds.bottom - pMark->Attributes.lrBounds.top) * 1000L) /
|
|
MarkImage.pImg->nHeight),
|
|
rRect, nScaleAlgorithm,
|
|
(LP_FIO_RGBQUAD) ((PSTR) pDib + sizeof(BITMAPINFOHEADER)),
|
|
pDib->biClrUsed))
|
|
FreeImgBuf(&MarkImage.pImg);
|
|
MoveImage(&pTempImg, &MarkImage.pImg);
|
|
SetRect(&rRect, 0, 0, MarkImage.pImg->nWidth, MarkImage.pImg->nHeight);
|
|
CheckError2(IPtoDIB (pImage, MarkImage.pImg, &pNewDib, rRect))
|
|
|
|
// adjust the mark bounds to the new resolution of the image
|
|
pMark->Attributes.lrBounds.right = pMark->Attributes.lrBounds.left + pNewDib->biWidth;
|
|
pMark->Attributes.lrBounds.bottom = pMark->Attributes.lrBounds.top + pNewDib->biHeight;
|
|
|
|
// copy palette info from old dib to new dib
|
|
if ((nScaleAlgorithm != OI_SCALE_ALG_AVERAGE_TO_GRAY4)
|
|
&& (nScaleAlgorithm != OI_SCALE_ALG_AVERAGE_TO_GRAY8)){
|
|
memcpy ((PSTR) pNewDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR) pDib + sizeof(BITMAPINFOHEADER), ((int) pDib->biClrUsed * 4));
|
|
}
|
|
// delete the old display dib and replace it with new resolution
|
|
// adjusted dib
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pNewDib,
|
|
sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed * 4) + (pNewDib->biSizeImage)))
|
|
pAnRotation->nHRes = pImage->nHRes;
|
|
pAnRotation->nVRes = pImage->nVRes;
|
|
FreeImgBuf(&MarkImage.pImg);
|
|
|
|
|
|
Exit:
|
|
DeInit(FALSE, TRUE);
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: MakeMarkFromDib
|
|
|
|
PURPOSE: This will make an annotation mark from a Dib.
|
|
|
|
****************************************************************************/
|
|
|
|
int WINAPI MakeMarkFromDib(PBITMAPINFOHEADER pDib, PMARK *ppMark,
|
|
int nHRes, int nVRes){
|
|
|
|
int nStatus = 0;
|
|
PAN_IMAGE_STRUCT pAnImage;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
|
|
|
|
if (!pDib->biClrUsed){
|
|
if (pDib->biBitCount == 1){
|
|
pDib->biClrUsed = 2;
|
|
}
|
|
if (pDib->biBitCount == 4){
|
|
pDib->biClrUsed = 16;
|
|
}
|
|
if (pDib->biBitCount == 8){
|
|
pDib->biClrUsed = 256;
|
|
}
|
|
}
|
|
|
|
pAnImage = 0;
|
|
CheckError2(AddAMarkNamedBlock(*ppMark, szOiDIB,
|
|
(PPSTR) &pAnImage, sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed*4) + (pDib->biSizeImage)))
|
|
memcpy (pAnImage->dibInfo, pDib,
|
|
sizeof(BITMAPINFOHEADER) + (pDib->biClrUsed*4) + (pDib->biSizeImage));
|
|
|
|
pAnRotation = 0;
|
|
CheckError2(AddAMarkNamedBlock(*ppMark, szOiAnoDat,
|
|
(PPSTR) &pAnRotation, sizeof (AN_NEW_ROTATE_STRUCT)))
|
|
// Default rotation info to the original image condition
|
|
pAnRotation->rotation = 1;
|
|
pAnRotation->scale = 1000;
|
|
pAnRotation->bFormMark = FALSE;
|
|
pAnRotation->bClipboardOp = FALSE;
|
|
|
|
// Resolution info
|
|
pAnRotation->nHRes = nHRes;
|
|
pAnRotation->nVRes = nVRes;
|
|
pAnRotation->nOrigHRes = nHRes;
|
|
pAnRotation->nOrigVRes = nVRes;
|
|
|
|
(*ppMark)->Attributes.uType = OIOP_AN_IMAGE;
|
|
(*ppMark)->Attributes.bVisible = TRUE;
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/******************************************************************************
|
|
|
|
FUNCTION: GetFileName
|
|
|
|
PURPOSE: To do the stuff needed to get an image by reference filename
|
|
from the form x:filename where x is the path defined in win.ini
|
|
If it is already a filename then it just returns that string
|
|
|
|
*********************************************************************************/
|
|
void WINAPI GetFileName(PSTR pFileName, PCSTR pOrigName){
|
|
|
|
static char szatoistr[256];
|
|
char *npszatoistr;
|
|
char szSection[12];
|
|
char szEntry [12];
|
|
char szDefaultEntry[5];
|
|
char szReturnBuffer[256];
|
|
char szstr[3];
|
|
PSTR pszstr;
|
|
PSTR pszSection;
|
|
PSTR pszEntry;
|
|
PCSTR pszDefaultEntry;
|
|
PCSTR pszReturnBuffer;
|
|
|
|
|
|
strncpy(szatoistr, pOrigName, 255);
|
|
// set a near pointer to the filename string passed in
|
|
// to overcome the DS!=SS problem
|
|
npszatoistr = szatoistr;
|
|
// if filename passed in is of the form 'x:' where x = 1-9
|
|
// do special handling to get the actual file name
|
|
if ((isdigit (*npszatoistr)) && (atoi(npszatoistr) != 0)
|
|
&& ((*(npszatoistr + 1)) == ':')){
|
|
// must go to the win.ini O/i ImagePath section and look
|
|
// for path next to a number
|
|
pszSection = szSection;
|
|
LoadString (hInst, ID_OI_IMAGE_PATH, pszSection, 80);
|
|
pszstr = szstr;
|
|
// this gets the number in the file name which must be
|
|
// obtained to get the right path from win.ini
|
|
*pszstr = *pOrigName;
|
|
*(pszstr + 1) = '\0';
|
|
// pszstr now points to the number in the O/i ImagePath section
|
|
strcpy (szEntry, pszstr);
|
|
pszEntry = szEntry;
|
|
strcpy (szDefaultEntry, "c:\\");
|
|
pszDefaultEntry = szDefaultEntry;
|
|
pszReturnBuffer = szReturnBuffer;
|
|
// go to the woi.ini and get the path
|
|
GetProfileString(pszSection, pszEntry,
|
|
pszDefaultEntry, (PSTR) pszReturnBuffer, 256);
|
|
// point to the character after : in the filename passed in
|
|
pszstr = npszatoistr + 2;
|
|
// now create the valid path and file name by concating
|
|
// the filename passed in and the path gotten from the ini
|
|
strcat ((PSTR) pszReturnBuffer, pszstr);
|
|
strcpy (pFileName, pszReturnBuffer);
|
|
}else{ // if filename is already valid, just return it
|
|
strcpy (pFileName, pOrigName);
|
|
}
|
|
}
|
|
//
|
|
/******************************************************************************
|
|
|
|
FUNCTION: GetPageNumandFileName
|
|
|
|
PURPOSE: To get the page no. embedded in the filename. The format is
|
|
"filename|page"
|
|
*********************************************************************************/
|
|
void WINAPI GetPageNumandFileName(PSTR pRealFilename, PINT pnPage, PSTR pOrigName){
|
|
|
|
PSTR pTempPointer;
|
|
|
|
*pnPage = 1;
|
|
// this will search for filenames with embedded page no.s.
|
|
// The format is "filename|page"
|
|
strcpy (pRealFilename, pOrigName);
|
|
pTempPointer = pRealFilename;
|
|
while (*pTempPointer != '\0'){// search for end of string
|
|
if (*pTempPointer == '|'){
|
|
*pnPage = atoi(pTempPointer + 1);
|
|
*pTempPointer = '\0';
|
|
break;
|
|
}
|
|
pTempPointer++;
|
|
}
|
|
}
|
|
//
|
|
/******************************************************************************
|
|
|
|
FUNCTION: EmbedImageData
|
|
|
|
PURPOSE: Change reference marks, like image by reference and forms to
|
|
non reference marks like embedded images
|
|
|
|
*********************************************************************************/
|
|
int WINAPI EmbedImageData(HWND hWnd, PMARK pMark, PANO_IMAGE pAnoImage){
|
|
|
|
int nStatus = 0;
|
|
|
|
PAN_IMAGE_STRUCT pAnImage = 0;
|
|
PAN_NAME_STRUCT pAnName = 0;
|
|
PSTR pFileName;
|
|
char FileName[256];
|
|
IMAGE TempImage;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation;
|
|
PIMG pTempImg = 0;
|
|
RECT rRect;
|
|
PBITMAPINFOHEADER pDib;
|
|
PBITMAPINFOHEADER pNewDib;
|
|
PIMAGE pImage;
|
|
|
|
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage))
|
|
if (!pAnImage){ // create the dib from the name
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiFilNam, (PPSTR) &pAnName))
|
|
if (!pAnName){
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
pImage = pAnoImage->pBaseImage;
|
|
|
|
pFileName = FileName;
|
|
GetFileName (pFileName, (PSTR) pAnName->name);
|
|
CheckError2(OiImageToDib (hWnd, pFileName, &pDib))
|
|
|
|
CheckError2(DibToIpNoPal(&TempImage.pImg, pDib))
|
|
TempImage.nHeight = (int) (int) pDib->biHeight;
|
|
TempImage.nWidth = (int) pDib->biWidth;
|
|
|
|
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
|
|
|
|
if (nStatus = RotateImage (pMark, &TempImage, pAnRotation->rotation)){
|
|
goto Exit;
|
|
}
|
|
SetRect(&rRect, 0, 0, TempImage.pImg->nWidth, TempImage.pImg->nHeight);
|
|
|
|
CheckError2(ScaleImage(TempImage.pImg, &pTempImg, pAnRotation->scale,
|
|
pAnRotation->scale, rRect, 1,
|
|
(LP_FIO_RGBQUAD) ((PSTR) pDib + sizeof(BITMAPINFOHEADER)),
|
|
pDib->biClrUsed))
|
|
|
|
FreeImgBuf(&TempImage.pImg);
|
|
MoveImage(&pTempImg, &TempImage.pImg);
|
|
SetRect(&rRect, 0, 0, TempImage.pImg->nWidth, TempImage.pImg->nHeight);
|
|
CheckError2(IPtoDIB (pImage, TempImage.pImg, &pNewDib, rRect))
|
|
memcpy ((PSTR) pNewDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR) pDib + sizeof(BITMAPINFOHEADER), ((int) pDib->biClrUsed*4));
|
|
|
|
pAnImage = 0;
|
|
CheckError2(AddAMarkNamedBlock(pMark, szOiDIB,
|
|
(PPSTR) &pAnImage, sizeof(BITMAPINFOHEADER) +
|
|
(pNewDib->biClrUsed*4) + (pNewDib->biSizeImage)))
|
|
memcpy (pAnImage->dibInfo, pNewDib,
|
|
sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage));
|
|
|
|
FreeImgBuf(&TempImage.pImg);
|
|
FreeMemory((PPSTR) &pDib);
|
|
FreeMemory((PPSTR) &pNewDib);
|
|
}
|
|
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
pMark->Attributes.bTransparent = TRUE;
|
|
}
|
|
(int) pMark->Attributes.uType = OIOP_AN_IMAGE;
|
|
|
|
|
|
Exit:
|
|
return (nStatus);
|
|
}
|