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.
2811 lines
110 KiB
2811 lines
110 KiB
/****************************************************************************
|
|
COPY.C
|
|
|
|
$Log: S:\products\wangview\oiwh\display\copy.c_v $
|
|
*
|
|
* Rev 1.48 22 Apr 1996 06:48:46 BEG06016
|
|
* Cleaned up error checking.
|
|
*
|
|
* Rev 1.47 11 Apr 1996 15:13:14 BEG06016
|
|
* Optimized named block access some.
|
|
*
|
|
* Rev 1.46 05 Mar 1996 07:44:30 BEG06016
|
|
* Added color and gamma correction.
|
|
* Fixed access violations when freeing pattern brush bitmaps.
|
|
* This is not complete but will allow unlocking of most files.
|
|
*
|
|
* Rev 1.45 09 Jan 1996 14:06:56 BLJ
|
|
* Fixed rendering.
|
|
*
|
|
* Rev 1.44 04 Jan 1996 14:29:06 BLJ
|
|
* Fixed a memory manager bug.
|
|
*
|
|
* Rev 1.43 02 Jan 1996 09:58:22 BLJ
|
|
* Changed alot of UINTs to ints.
|
|
* Changed IMG structure to include the image data.
|
|
* Changed lp prefix to p.
|
|
*
|
|
* Rev 1.42 22 Dec 1995 11:12:20 BLJ
|
|
* Added a parameter for zero init'ing to some memory manager calls.
|
|
*
|
|
* Rev 1.41 15 Nov 1995 13:51:50 BLJ
|
|
* Fixed 5266 scrolling image data left.
|
|
*
|
|
* Rev 1.40 10 Nov 1995 10:51:16 BLJ
|
|
* Fixed runtime part of 5142 - IMGClearImage nows work properly.
|
|
*
|
|
* Rev 1.39 09 Nov 1995 13:53:42 BLJ
|
|
* Fixed 5262 - RGB24 Image gets corrupted when scrolled left followed by right.
|
|
*
|
|
* Rev 1.38 13 Oct 1995 12:27:28 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.
|
|
*
|
|
* Rev 1.37 12 Oct 1995 13:48:48 RC
|
|
* Passed in scalealg to convresbm rather than calculating it
|
|
*
|
|
* Rev 1.36 09 Oct 1995 13:53:24 BLJ
|
|
* Moved the paste information from pWindow to pAnoImage.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "privdisp.h"
|
|
|
|
int WINAPI PaletteSize (VOID * pv);
|
|
int WINAPI DibNumColors (VOID * pv);
|
|
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: IMGClipboardCgbw
|
|
|
|
PURPOSE: The function handles all operations involving the clipboard.
|
|
|
|
INPUT: hWnd - Identifies the image window.
|
|
nClipAction - A constant indicating the type of clipboard
|
|
operation to perform.
|
|
pParm - A pointer to the clipboard parameters.
|
|
nFlags - Flags indicating how or what to get the information.
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI IMGClipboardCgbw(HWND hWnd, int nClipAction, void *pParm, int nFlags){
|
|
|
|
int nStatus = 0;
|
|
|
|
PWINDOW pWindow;
|
|
PANO_IMAGE pAnoImage;
|
|
PIMAGE pImage;
|
|
|
|
PMARK pMark;
|
|
int nMarkIndex;
|
|
|
|
HANDLE hPalette = 0;
|
|
HANDLE hBitmap = 0;
|
|
int nScaledWidth;
|
|
int nScaledHeight;
|
|
CLIP_COPY_STRUCT ClipCopy;
|
|
//LRECT lrRect;
|
|
LRECT PasteRect;
|
|
int nHScale;
|
|
int nVScale;
|
|
HANDLE hDib = 0;
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
BOOL fDeletePasteDib = FALSE;
|
|
long lHScale;
|
|
long lVScale;
|
|
BOOL bClipBoardOpen = FALSE;
|
|
PSTR pBlock;
|
|
|
|
|
|
CheckError2( Init(hWnd, &pWindow, &pAnoImage, TRUE, TRUE));
|
|
|
|
// Check for operation in progress.
|
|
if (pAnoImage->Annotations.ppMarks){
|
|
pMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
|
|
if (pMark){
|
|
OiOpEndOperation(hWnd);
|
|
pMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
|
|
if (pMark){
|
|
OiOpEndOperation(hWnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
pImage = pAnoImage->pBaseImage;
|
|
|
|
if (pParm == NULL){
|
|
nStatus = Error(DISPLAY_NULLPOINTERINVALID);
|
|
goto Exit;
|
|
}
|
|
|
|
CheckError2( ValidateCache(hWnd, pAnoImage));
|
|
|
|
if (!OpenClipboard(hWnd)){
|
|
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
|
|
goto Exit;
|
|
}
|
|
bClipBoardOpen = TRUE;
|
|
|
|
// Delete OiError named blocks.
|
|
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
CheckError2( DeleteAMarkNamedBlock(pMark, szOiError));
|
|
}
|
|
|
|
switch (nClipAction){
|
|
case CLIP_COPY:
|
|
ClipCopy = *((PCLIP_COPY_STRUCT) pParm);
|
|
ClipCopy.nScale = SD_FULLSIZE;
|
|
ClipCopy.bUseCurrentScale = FALSE;
|
|
CheckError2( ClipboardCopy(hWnd, pWindow, pAnoImage, pImage, &ClipCopy, nFlags));
|
|
break;
|
|
|
|
case CLIP_CUT:
|
|
ClipCopy = *((PCLIP_COPY_STRUCT) pParm);
|
|
ClipCopy.nScale = SD_FULLSIZE;
|
|
ClipCopy.bUseCurrentScale = FALSE;
|
|
if (ClipCopy.lRect.right == 0){
|
|
GetSelectBox(pAnoImage, &ClipCopy.lRect);
|
|
}else{
|
|
if ((ClipCopy.lRect.right - ClipCopy.lRect.left) > 0
|
|
|| (ClipCopy.lRect.bottom - ClipCopy.lRect.top) > 0){
|
|
if (nFlags & PARM_SCALED){
|
|
ConvertRect(pWindow, &ClipCopy.lRect, CONV_SCALED_TO_FULLSIZE);
|
|
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
|
|
ConvertRect(pWindow, &ClipCopy.lRect, CONV_WINDOW_TO_FULLSIZE);
|
|
}
|
|
}
|
|
}
|
|
nFlags = (nFlags & ~(PARM_WINDOW | PARM_SCALED)) | PARM_FULLSIZE;
|
|
|
|
// Check permissions for delete privileges.
|
|
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
if (pMark->bSelected){
|
|
if (!(pMark->Attributes.dwPermissions & ACL_DELETE_MARK)){
|
|
pBlock = 0;
|
|
CheckError2( AddAMarkNamedBlock(pMark, szOiError, &pBlock, 1L));
|
|
nStatus = Error(DISPLAY_RESTRICTED_ACCESS);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
CheckError2( ClipboardCopy(hWnd, pWindow, pAnoImage, pImage, &ClipCopy, nFlags));
|
|
|
|
// ClipboardCopy will convert ClipCopy.lRect to FULLSIZE.
|
|
CheckError2( ClearImage(pWindow, pImage, &ClipCopy.lRect));
|
|
|
|
// Delete selected marks.
|
|
for (nMarkIndex = pAnoImage->Annotations.nMarks - 1; nMarkIndex >= 0; nMarkIndex--){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
if (pMark->bSelected){
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
CheckError2( InvalidateAllDisplayRects(pWindow, pImage, NULL, TRUE));
|
|
}
|
|
CheckError2( DeleteMark(pAnoImage, nMarkIndex));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CLIP_PASTE:
|
|
CopyRect(PasteRect, *((LPLRECT) pParm));
|
|
if ((PasteRect.right - PasteRect.left) <= 0
|
|
|| (PasteRect.bottom - PasteRect.top) <= 0){
|
|
GetSelectBox(pAnoImage, &PasteRect);
|
|
}else{
|
|
if ((PasteRect.right - PasteRect.left) <= 0
|
|
|| (PasteRect.bottom - PasteRect.top) <= 0){
|
|
nStatus = Error(DISPLAY_INVALIDRECT);
|
|
goto Exit;
|
|
}
|
|
if (nFlags & PARM_SCALED){
|
|
ConvertRect(pWindow, &PasteRect, CONV_SCALED_TO_FULLSIZE);
|
|
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
|
|
ConvertRect(pWindow, &PasteRect, CONV_WINDOW_TO_FULLSIZE);
|
|
}
|
|
}
|
|
if ((PasteRect.right - PasteRect.left) <= 0
|
|
|| (PasteRect.bottom - PasteRect.top) <= 0
|
|
|| PasteRect.right > pImage->nWidth
|
|
|| PasteRect.bottom > pImage->nHeight){
|
|
nStatus = Error(DISPLAY_INVALIDRECT);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get clipboard data.
|
|
|
|
hBitmap = GetClipboardData(CF_BITMAP);
|
|
hDib = GetClipboardData(CF_DIB);
|
|
|
|
// Don't check for errors for this call!
|
|
// No handle simply means no palette.
|
|
hPalette = GetClipboardData(CF_PALETTE);
|
|
|
|
if (!hBitmap && !hDib){
|
|
nStatus = Error(DISPLAY_NO_CLIPBOARD);
|
|
goto Exit;
|
|
}else if (hBitmap && !hDib){
|
|
CheckError2( DibFromBitmap (hBitmap, hPalette, &pDib));
|
|
fDeletePasteDib = TRUE;
|
|
}else if (hDib && hPalette){
|
|
CheckError2( CorrectDibPalette(hPalette, pDib));
|
|
}
|
|
|
|
if (!(pDib = (VOID *) GlobalLock(hDib))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
|
|
// Do this in long math to avoid overflow.
|
|
nScaledWidth = (PasteRect.right - PasteRect.left);
|
|
nScaledHeight = (PasteRect.bottom - PasteRect.top);
|
|
lHScale = ((nScaledWidth * 1000) / (int) pDib->biWidth);
|
|
lVScale = ((nScaledHeight * 1000) / (int) pDib->biHeight);
|
|
|
|
while (((int) pDib->biWidth * lHScale / 1000) < nScaledWidth){
|
|
lHScale++;
|
|
}
|
|
while (((int) pDib->biHeight * lVScale / 1000) < nScaledHeight){
|
|
lVScale++;
|
|
}
|
|
|
|
if ((lHScale > 65535) || (lVScale > 65535) || (lHScale < 20) || (lVScale < 20)){
|
|
// Scale too big.
|
|
nStatus = Error(DISPLAY_INVALIDSCALE);
|
|
goto Exit;
|
|
}
|
|
nHScale = (lHScale);
|
|
nVScale = (lVScale);
|
|
|
|
CheckError2( RenderDibToImage(&pAnoImage->pBaseImage->pImg,
|
|
pDib, nHScale, nVScale, PasteRect));
|
|
|
|
pImage->bArchive |= ARCHIVE_PASTED_INTO_IMAGE;
|
|
if (pAnoImage->pBasePlusFormImg != pImage->pImg){
|
|
CheckError2( FreeImgBuf(&pAnoImage->pBasePlusFormImg));
|
|
CheckError2( FreeMemory((PPSTR) &pAnoImage->pBasePlusFormImg));
|
|
}
|
|
pAnoImage->nBPFValidLines = 0;
|
|
CheckError2( InvalidateAllDisplayRects(pWindow, pImage, &PasteRect, TRUE));
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_INVALID_OPTIONS); // nClipAction is invalid.
|
|
goto Exit;
|
|
}
|
|
|
|
// SetLRect(lrRect, 0, 0, 0, 0);
|
|
// if (nStatus = IMGSetParmsCgbw(hWnd, PARM_SELECTION_BOX, &lrRect, PARM_FULLSIZE)){
|
|
// goto Exit;
|
|
// }
|
|
if (!(nFlags & PARM_DONT_REPAINT)){
|
|
CheckError2( IMGRepaintDisplay(hWnd, NULL));
|
|
}
|
|
|
|
Exit:
|
|
if (bClipBoardOpen){
|
|
CloseClipboard();
|
|
}
|
|
if (hDib){
|
|
GlobalUnlock(hDib);
|
|
}
|
|
|
|
if (nClipAction != CLIP_PASTE){ // Can't free handles that aren't mine.
|
|
if (hBitmap){
|
|
DeleteObject(hBitmap);
|
|
}
|
|
}
|
|
|
|
// Can't free handles that aren't mine.
|
|
if (nClipAction != CLIP_PASTE || fDeletePasteDib){
|
|
if (hDib){
|
|
GlobalFree(hDib);
|
|
}
|
|
}
|
|
|
|
DeInit(TRUE, TRUE);
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: ClipboardCopy
|
|
|
|
PURPOSE: The function handles copy operations involving the clipboard.
|
|
|
|
INPUT: hWnd - Identifies the image window.
|
|
pParm - A pointer to the clipboard parameters.
|
|
nFlags - Flags indicating how or what to get the information.
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI ClipboardCopy(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
|
|
PIMAGE pImage, PCLIP_COPY_STRUCT pClipCopy, int nFlags){
|
|
|
|
int nStatus = 0;
|
|
|
|
PMARK pMark;
|
|
MARK Mark;
|
|
MARK NewMarks[4];
|
|
PMARK pNewMarks;
|
|
PMARK pMark2;
|
|
int nMarkIndex;
|
|
int nMarkIndex2;
|
|
int nMarkIndex3;
|
|
|
|
int nHScale;
|
|
int nVScale;
|
|
HANDLE hDib = 0;
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
LRECT lCopyRect;
|
|
PSTR pBlock;
|
|
LRECT lrCopyBounds;
|
|
HGLOBAL hGlobal;
|
|
long lTemp;
|
|
int nNamedBlockIndex;
|
|
int nMarks = 0;
|
|
LRECT lrRect;
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation =0;
|
|
|
|
// Get and validate parameters.
|
|
if (pClipCopy->lRect.right == 0){
|
|
GetSelectBox(pAnoImage, &lCopyRect);
|
|
}else{
|
|
if ((pClipCopy->lRect.right - pClipCopy->lRect.left) > 0
|
|
|| (pClipCopy->lRect.bottom - pClipCopy->lRect.top) > 0){
|
|
CopyRect(lCopyRect, pClipCopy->lRect);
|
|
if (nFlags & PARM_SCALED){
|
|
ConvertRect(pWindow, &lCopyRect, CONV_SCALED_TO_FULLSIZE);
|
|
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
|
|
ConvertRect(pWindow, &lCopyRect, CONV_WINDOW_TO_FULLSIZE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lCopyRect.right > pImage->nWidth
|
|
|| lCopyRect.bottom > pImage->nHeight){
|
|
nStatus = Error(DISPLAY_INVALIDRECT);
|
|
goto Exit;
|
|
}
|
|
|
|
#ifdef old
|
|
if (pClipCopy->bUseCurrentScale){
|
|
nHScale = pWindow->nScale;
|
|
}else{
|
|
nHScale = pClipCopy->nScale;
|
|
}
|
|
if (nHScale < 20){
|
|
switch (nHScale){
|
|
case SD_EIGHTXSIZE: nHScale = SCALE_DENOMINATOR * 8; break;
|
|
case SD_FOURXSIZE: nHScale = SCALE_DENOMINATOR * 4; break;
|
|
case SD_TWOXSIZE: nHScale = SCALE_DENOMINATOR * 2; break;
|
|
case SD_FULLSIZE: nHScale = SCALE_DENOMINATOR * 1; break;
|
|
case SD_HALFSIZE: nHScale = SCALE_DENOMINATOR / 2; break;
|
|
case SD_QUARTERSIZE: nHScale = SCALE_DENOMINATOR / 4; break;
|
|
case SD_EIGHTHSIZE: nHScale = SCALE_DENOMINATOR / 8; break;
|
|
case SD_SIXTEENTHSIZE: nHScale = SCALE_DENOMINATOR /16; break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_INVALIDSCALE);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (nHScale == 1000){
|
|
nVScale = nHScale;
|
|
}else{
|
|
CheckError2( TranslateScale(nHScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale));
|
|
}
|
|
#endif
|
|
nHScale = 1000;
|
|
nVScale = 1000;
|
|
|
|
// Partial select all marks.
|
|
CheckError2( CheckSelection(pAnoImage, ACL_MUST_INCLUDE_IN_COPY));
|
|
|
|
// Find the bounding rect of the copy operation.
|
|
CopyRect(lrCopyBounds, lCopyRect);
|
|
if (lrCopyBounds.left == lrCopyBounds.right || lrCopyBounds.top == lrCopyBounds.bottom){
|
|
SetLRect(lrCopyBounds, pImage->nWidth + 10, pImage->nHeight + 10, 0, 0);
|
|
}
|
|
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
if (pMark->bSelected || pMark->bTempSelected){
|
|
if (!(pMark->Attributes.dwPermissions & ACL_COPY_MARK)){
|
|
pBlock = 0;
|
|
CheckError2( AddAMarkNamedBlock(pMark, szOiError, &pBlock, 1L));
|
|
nStatus = Error(DISPLAY_RESTRICTED_ACCESS);
|
|
goto Exit;
|
|
}
|
|
if (((int) pMark->Attributes.uType == OIOP_AN_LINE) ||
|
|
((int) pMark->Attributes.uType == OIOP_AN_FREEHAND) ||
|
|
((int) pMark->Attributes.uType == OIOP_AN_HOLLOW_RECT)){
|
|
lrCopyBounds.left = lmin(lrCopyBounds.left, pMark->Attributes.lrBounds.left -
|
|
(((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrCopyBounds.top = lmin(lrCopyBounds.top, pMark->Attributes.lrBounds.top -
|
|
(((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrCopyBounds.right = lmax(lrCopyBounds.right, pMark->Attributes.lrBounds.right +
|
|
(((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrCopyBounds.bottom = lmax(lrCopyBounds.bottom, pMark->Attributes.lrBounds.bottom +
|
|
(((int) pMark->Attributes.uLineSize + 1)/2));
|
|
}else{
|
|
lrCopyBounds.left = lmin(lrCopyBounds.left, pMark->Attributes.lrBounds.left);
|
|
lrCopyBounds.top = lmin(lrCopyBounds.top, pMark->Attributes.lrBounds.top);
|
|
lrCopyBounds.right = lmax(lrCopyBounds.right, pMark->Attributes.lrBounds.right);
|
|
lrCopyBounds.bottom = lmax(lrCopyBounds.bottom, pMark->Attributes.lrBounds.bottom);
|
|
}
|
|
}
|
|
}
|
|
pAnoImage->bAnoBlockUseMemOnly = TRUE;
|
|
pAnoImage->hpAnoBlock = 0;
|
|
pAnoImage->lAnoBlockIndex = 0;
|
|
pAnoImage->lAnoBlockCount = 0;
|
|
|
|
// Reserve space for length.
|
|
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->lAnoBlockCount));
|
|
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->pBaseImage->nHRes));
|
|
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->pBaseImage->nVRes));
|
|
// Set for 32 bit Intel format.
|
|
lTemp = 1;
|
|
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &lTemp));
|
|
|
|
// Copy the image if there is a selection box on the image
|
|
if ((lCopyRect.right - lCopyRect.left) > 0
|
|
|| (lCopyRect.bottom - lCopyRect.top) > 0){
|
|
CheckError2( MakeDibFromImage(pImage, lCopyRect, &pDib, nHScale, nVScale));
|
|
pMark = &Mark;
|
|
memset(pMark, 0, sizeof(MARK));
|
|
CheckError2( MakeMarkFromDib(pDib, &pMark, pImage->nHRes, pImage->nVRes));
|
|
CheckError2( FreeMemory((PPSTR) &pDib));
|
|
SetLRect(pMark->Attributes.lrBounds,
|
|
lCopyRect.left - lrCopyBounds.left,
|
|
lCopyRect.top - lrCopyBounds.top,
|
|
lCopyRect.right - lrCopyBounds.left,
|
|
lCopyRect.bottom - lrCopyBounds.top);
|
|
|
|
pBlock = 0;
|
|
CheckError2( AddAMarkNamedBlock(pMark, szOiBaseIm, &pBlock, 1L));
|
|
CheckError2( SaveMark(hWnd, pAnoImage, pMark, nHScale, nVScale, OI_SCALE_ALG_NORMAL));
|
|
|
|
// delete the dib mark
|
|
// Free the named block info.
|
|
CheckError2( DeleteMarkNamedBlocks(pMark));
|
|
}
|
|
|
|
// Copy all selected annotation marks.
|
|
for (nMarkIndex = 0; nMarkIndex < (int) pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
// if it is a form type then change to image type
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
|
|
(int) pMark->Attributes.uType = OIOP_AN_IMAGE;
|
|
pMark->Attributes.bTransparent = TRUE;
|
|
pAnRotation->bFormMark = TRUE;
|
|
pAnRotation->bClipboardOp = TRUE;
|
|
}
|
|
|
|
if (pMark->bSelected || pMark->bTempSelected){
|
|
if (!pMark->bSelected && pMark->bTempSelected){
|
|
pNewMarks = NewMarks;
|
|
for (nMarkIndex2 = 0; nMarkIndex2 < 4; nMarkIndex2++){
|
|
memset(&NewMarks[nMarkIndex2], 0, sizeof(MARK));
|
|
}
|
|
|
|
GetSelectBox (pAnoImage, &lrRect);
|
|
if (lrRect.left < pMark->Attributes.lrBounds.right
|
|
&& lrRect.right > pMark->Attributes.lrBounds.left
|
|
&& lrRect.top < pMark->Attributes.lrBounds.bottom
|
|
&& lrRect.bottom > pMark->Attributes.lrBounds.top){
|
|
CheckError2( CreatePartialMark(hWnd, pNewMarks, pMark, lrRect, &nMarks));
|
|
for (nMarkIndex2 = 0; nMarkIndex2 < nMarks; nMarkIndex2++){
|
|
CheckError2( SaveMark(hWnd, pAnoImage, &NewMarks[nMarkIndex2],
|
|
nHScale, nVScale, OI_SCALE_ALG_NORMAL));
|
|
|
|
if (NewMarks[nMarkIndex2].ppNamedBlock){
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < NewMarks[nMarkIndex2].nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( FreeMemory(&NewMarks[nMarkIndex2].ppNamedBlock[nNamedBlockIndex]->pBlock));
|
|
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex2].ppNamedBlock[nNamedBlockIndex]));
|
|
}
|
|
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex2].ppNamedBlock));
|
|
}
|
|
}
|
|
|
|
continue;
|
|
}
|
|
// for must include mark, check to see if there are any
|
|
// selected marks below it, if so create partial mark from
|
|
// the must include mark
|
|
for (nMarkIndex2 = nMarkIndex; nMarkIndex2 >= 0; nMarkIndex2--){
|
|
pMark2 = pAnoImage->Annotations.ppMarks[nMarkIndex2];
|
|
if (pMark2->bSelected){
|
|
if (pMark2->Attributes.lrBounds.left < pMark->Attributes.lrBounds.right
|
|
&& pMark2->Attributes.lrBounds.right > pMark->Attributes.lrBounds.left
|
|
&& pMark2->Attributes.lrBounds.top < pMark->Attributes.lrBounds.bottom
|
|
&& pMark2->Attributes.lrBounds.bottom > pMark->Attributes.lrBounds.top){
|
|
CheckError2( CreatePartialMark(hWnd, pNewMarks,
|
|
pMark, pMark2->Attributes.lrBounds, &nMarks));
|
|
for (nMarkIndex3 = 0; nMarkIndex3 < nMarks; nMarkIndex3++){
|
|
CheckError2( SaveMark(hWnd, pAnoImage, &NewMarks[nMarkIndex3],
|
|
nHScale, nVScale, OI_SCALE_ALG_NORMAL));
|
|
|
|
if (NewMarks[nMarkIndex3].ppNamedBlock){
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex
|
|
< NewMarks[nMarkIndex3].nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( FreeMemory(&NewMarks[nMarkIndex3].ppNamedBlock[nNamedBlockIndex]->pBlock));
|
|
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex3].ppNamedBlock[nNamedBlockIndex]));
|
|
}
|
|
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex3].ppNamedBlock));
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
SetLRect(pMark->Attributes.lrBounds,
|
|
pMark->Attributes.lrBounds.left - lrCopyBounds.left,
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top,
|
|
pMark->Attributes.lrBounds.right - lrCopyBounds.left,
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
|
|
|
|
CheckError2( SaveMark(hWnd, pAnoImage, pMark, nHScale, nVScale, OI_SCALE_ALG_NORMAL));
|
|
SetLRect(pMark->Attributes.lrBounds,
|
|
pMark->Attributes.lrBounds.left + lrCopyBounds.left,
|
|
pMark->Attributes.lrBounds.top + lrCopyBounds.top,
|
|
pMark->Attributes.lrBounds.right + lrCopyBounds.left,
|
|
pMark->Attributes.lrBounds.bottom + lrCopyBounds.top);
|
|
}
|
|
}
|
|
// change form mark back from image type, now that save is done
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE){
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
|
|
if (pAnRotation->bFormMark){
|
|
(int) pMark->Attributes.uType = OIOP_AN_FORM;
|
|
pMark->Attributes.bTransparent = FALSE;
|
|
pAnRotation->bFormMark = FALSE;
|
|
pAnRotation->bClipboardOp = FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Set length to correct value.
|
|
*((long *) pAnoImage->hpAnoBlock) = pAnoImage->lAnoBlockIndex;
|
|
*((long *) (pAnoImage->hpAnoBlock + 4)) = pAnoImage->pBaseImage->nHRes;
|
|
*((long *) (pAnoImage->hpAnoBlock + 8)) = pAnoImage->pBaseImage->nVRes;
|
|
|
|
// Move the data to the clipboard.
|
|
EmptyClipboard();
|
|
if (pAnoImage->pWangAnnotatedImageFormat){
|
|
CheckError2( FreeMemory(&pAnoImage->pWangAnnotatedImageFormat));
|
|
}
|
|
pAnoImage->pWangAnnotatedImageFormat = pAnoImage->hpAnoBlock;
|
|
pAnoImage->hpAnoBlock = 0;
|
|
pAnoImage->lAnoBlockIndex = 0;
|
|
pAnoImage->lAnoBlockCount = 0;
|
|
SetClipboardData(nWangAnnotatedImageFormat, NULL);
|
|
SetClipboardData(CF_DIB, NULL);
|
|
bRenderDib = TRUE;
|
|
bRenderWangAnnotatedIFormat = TRUE;
|
|
|
|
// This must remain GlobalAlloc.
|
|
if (!(hGlobal = GlobalAlloc(GHND | GMEM_DDESHARE, 1))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
SetClipboardData(nWangAnnotationFormat, hGlobal);
|
|
bRenderWangAnnotations = TRUE;
|
|
|
|
|
|
Exit:
|
|
if (pAnoImage->hpAnoBlock){
|
|
FreeMemory(&pAnoImage->pWangAnnotatedImageFormat);
|
|
pAnoImage->hpAnoBlock = 0;
|
|
pAnoImage->lAnoBlockIndex = 0;
|
|
pAnoImage->lAnoBlockCount = 0;
|
|
}
|
|
pAnoImage->bAnoBlockUseMemOnly = FALSE;
|
|
|
|
if (hDib){
|
|
GlobalFree(hDib);
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: StartPasteAnnotatedImage
|
|
|
|
PURPOSE: Pastes an annotated image from the clipboard.
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI StartPasteAnnotatedImage(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
|
|
PIMAGE pImage, LRECT lrRectPoint, int nFlags){
|
|
|
|
int nStatus = 0;
|
|
|
|
PMARK pMark;
|
|
PMARK pPasteMark;
|
|
int nMarkIndex;
|
|
|
|
LRECT lrPasteRect;
|
|
int nStartingMark;
|
|
int nEndingMark;
|
|
long lHOffset;
|
|
long lVOffset;
|
|
HPSTR hpClipData = 0;
|
|
HGLOBAL hClipData = 0;
|
|
int nResHScale = 0;
|
|
int nResVScale = 0;
|
|
|
|
// Get clipboard data.
|
|
// Calculate bounds of new marks.
|
|
|
|
// Deselect all.
|
|
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
pMark->bSelected = FALSE;
|
|
pMark->bTempSelected = FALSE;
|
|
}
|
|
|
|
// Save paste mark.
|
|
pPasteMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
|
|
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = 0;
|
|
|
|
// Copy marks being pasted into ppMarks.
|
|
if (!OpenClipboard(hWnd)){
|
|
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
|
|
goto Exit;
|
|
}
|
|
if (!(hClipData = GetClipboardData(nWangAnnotatedImageFormat))){
|
|
CloseClipboard();
|
|
nStatus = Error(DISPLAY_NO_CLIPBOARD);
|
|
goto Exit;
|
|
}
|
|
CloseClipboard();
|
|
if (!(hpClipData = GlobalLock(hClipData))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
// get the resolution adjustment stuff now
|
|
nResHScale = *((long *) (hpClipData + 4)); // (clipboard's) pBaseImage->nHRes.
|
|
nResHScale = (1000 * pImage->nHRes) / nResHScale;
|
|
nResVScale = *((long *) (hpClipData + 8)); // (clipboard's) pBaseImage->nVRes.
|
|
nResVScale = (1000 * pImage->nVRes) / nResVScale;
|
|
if (!nResHScale){
|
|
nResHScale = 1000;
|
|
}
|
|
if (!nResVScale){
|
|
nResVScale = (1000 * pImage->nHRes) / pImage->nVRes;
|
|
}
|
|
|
|
nStartingMark = pAnoImage->Annotations.nMarks;
|
|
pAnoImage->bAnoBlockUseMemOnly = TRUE;
|
|
pAnoImage->lAnoBlockCount = *((PLONG) hpClipData) - 12;
|
|
pAnoImage->hpAnoBlock = hpClipData;
|
|
pAnoImage->lAnoBlockIndex = 12;
|
|
|
|
CheckError2( ReadAnnotations(hWnd, pAnoImage,
|
|
&pAnoImage->Annotations.ppMarks, &pAnoImage->Annotations.nMarks));
|
|
nEndingMark = pAnoImage->Annotations.nMarks;
|
|
|
|
// Restore paste mark.
|
|
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pPasteMark;
|
|
|
|
// Delete the "Base Image" flag (named block) if pasting as an annotation.
|
|
if (pAnoImage->nPasteFormat == nWangAnnotationFormat){
|
|
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
CheckError2( DeleteAMarkNamedBlock(pMark, szOiBaseIm));
|
|
}
|
|
}
|
|
|
|
// Set paste mark's bounds.
|
|
SetLRect(lrPasteRect, 0, 0, 0, 0);
|
|
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
pMark->Attributes.dwPermissions = ACL_ALL;
|
|
pMark->bSelected = TRUE;
|
|
if (((int) pMark->Attributes.uType != OIOP_AN_IMAGE) &&
|
|
((int) pMark->Attributes.uType != OIOP_AN_IMAGE_BY_REFERENCE) &&
|
|
((int) pMark->Attributes.uType != OIOP_AN_FORM)){
|
|
CheckError2( ScaleAnnotation(hWnd, pMark, nResHScale, nResVScale, OI_SCALE_ALG_NORMAL));
|
|
}
|
|
lrPasteRect.right = lmax(lrPasteRect.right, pMark->Attributes.lrBounds.right);
|
|
lrPasteRect.bottom = lmax(lrPasteRect.bottom, pMark->Attributes.lrBounds.bottom);
|
|
}
|
|
|
|
// Place the data and adjust PasteRect offsets to keep pasted data on the image.
|
|
if ((nFlags & OIAN_UPPER_LEFT)){
|
|
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right);
|
|
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom);
|
|
}else{
|
|
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right - lrPasteRect.right / 2);
|
|
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom - lrPasteRect.bottom / 2);
|
|
}
|
|
lHOffset = lmax(lHOffset, -(lrPasteRect.right - 5));
|
|
lVOffset = lmax(lVOffset, -(lrPasteRect.bottom - 5));
|
|
|
|
// Adjust all mark's bounds including paste mark's bounds.
|
|
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
pMark->Attributes.lrBounds.left = pMark->Attributes.lrBounds.left + lHOffset;
|
|
pMark->Attributes.lrBounds.top = pMark->Attributes.lrBounds.top + lVOffset;
|
|
pMark->Attributes.lrBounds.right = pMark->Attributes.lrBounds.right + lHOffset;
|
|
pMark->Attributes.lrBounds.bottom = pMark->Attributes.lrBounds.bottom + lVOffset;
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (hpClipData){
|
|
GlobalUnlock(hClipData);
|
|
}
|
|
pAnoImage->bAnoBlockUseMemOnly = 0;
|
|
pAnoImage->lAnoBlockCount = 0;
|
|
pAnoImage->hpAnoBlock = 0;
|
|
pAnoImage->lAnoBlockIndex = 0;
|
|
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: StartPasteImage
|
|
|
|
PURPOSE: Pastes an image from the clipboard.
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI StartPasteImage(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
|
|
PIMAGE pImage, LRECT lrRectPoint, int nFlags){
|
|
|
|
int nStatus = 0;
|
|
|
|
PMARK pMark = 0;
|
|
PMARK pPasteMark;
|
|
int nMarkIndex;
|
|
|
|
LRECT lrPasteRect;
|
|
long lHOffset;
|
|
long lVOffset;
|
|
HGLOBAL hDib = 0;
|
|
HPSTR hpDib = 0;
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
PSTR pBlock;
|
|
|
|
|
|
// Get clipboard data.
|
|
// Calculate bounds of new marks.
|
|
|
|
// Deselect all.
|
|
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
|
|
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
|
|
pMark->bSelected = FALSE;
|
|
pMark->bTempSelected = FALSE;
|
|
}
|
|
|
|
// Copy Dib being pasted into ppMarks.
|
|
if (!OpenClipboard(hWnd)){
|
|
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
|
|
goto Exit;
|
|
}
|
|
if (!(hDib = GetClipboardData(CF_DIB))){
|
|
nStatus = Error(DISPLAY_NO_CLIPBOARD);
|
|
CloseClipboard();
|
|
goto Exit;
|
|
}
|
|
CloseClipboard();
|
|
if (!(hpDib = GlobalLock(hDib))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
pDib = (PBITMAPINFOHEADER) hpDib;
|
|
|
|
CheckError2( ReAllocateMemory(sizeof(PMARK) * (pAnoImage->Annotations.nMarks + 2),
|
|
(PPSTR) &pAnoImage->Annotations.ppMarks, ZERO_INIT));
|
|
CheckError2(AllocateMemory(sizeof(MARK), (PPSTR) &pMark, ZERO_INIT) );
|
|
|
|
// Save mark.
|
|
pPasteMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
|
|
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pMark;
|
|
pAnoImage->Annotations.nMarks++;
|
|
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pPasteMark;
|
|
|
|
CheckError2( MakeMarkFromDib(pDib, &pMark, pImage->nHRes, pImage->nVRes));
|
|
SetLRect(pMark->Attributes.lrBounds, 0, 0, (int) pDib->biWidth, (int) pDib->biHeight);
|
|
|
|
// Tag mark so it is burnt into the base image.
|
|
CheckError2( AllocateMemory(1L, &pBlock, NO_INIT));
|
|
pBlock = 0;
|
|
CheckError2( AddAMarkNamedBlock(pMark, szOiBaseIm, &pBlock, 1L));
|
|
|
|
// Set paste mark's bounds.
|
|
SetLRect(lrPasteRect, 0, 0, (int) pDib->biWidth, (int) pDib->biHeight);
|
|
pMark->Attributes.dwPermissions = ACL_ALL;
|
|
pMark->bSelected = TRUE;
|
|
|
|
// Place the data and adjust PasteRect offsets to keep pasted data on the image.
|
|
if ((nFlags & OIAN_UPPER_LEFT)){
|
|
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right);
|
|
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom);
|
|
}else{
|
|
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right - lrPasteRect.right / 2);
|
|
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom - lrPasteRect.bottom / 2);
|
|
}
|
|
lHOffset = lmax(lHOffset, -(lrPasteRect.right - 5));
|
|
lVOffset = lmax(lVOffset, -(lrPasteRect.bottom - 5));
|
|
|
|
// Adjust all mark's bounds.
|
|
pMark->Attributes.lrBounds.left = pMark->Attributes.lrBounds.left + lHOffset;
|
|
pMark->Attributes.lrBounds.top = pMark->Attributes.lrBounds.top + lVOffset;
|
|
pMark->Attributes.lrBounds.right = pMark->Attributes.lrBounds.right + lHOffset;
|
|
pMark->Attributes.lrBounds.bottom = pMark->Attributes.lrBounds.bottom + lVOffset;
|
|
|
|
|
|
Exit:
|
|
if (hpDib){
|
|
GlobalUnlock(hDib);
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: MakeDibFromImage
|
|
|
|
PURPOSE: This will make a DIB from the specified portion of the image.
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI MakeDibFromImage(PIMAGE pImage, LRECT lRect, PBITMAPINFOHEADER *ppDib,
|
|
int nHScale, int nVScale){
|
|
|
|
int nStatus = 0;
|
|
|
|
PIMG pImg = 0;
|
|
RECT Rect;
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
|
|
|
|
// Copy the image.
|
|
CopyRectLtoR(Rect, lRect);
|
|
if (nHScale == 1000){
|
|
CheckError2( IPtoDIB(pImage, pImage->pImg, &pDib, Rect));
|
|
}else{
|
|
CheckError2( ScaleImage(pImage->pImg, &pImg, nHScale, nVScale, Rect, 0,
|
|
pImage->PaletteTable, pImage->nPaletteEntries));
|
|
|
|
SetRect(&Rect, 0, 0, pImg->nWidth, pImg->nHeight);
|
|
|
|
CheckError2( IPtoDIB(pImage, pImg, &pDib, Rect));
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (nStatus){
|
|
FreeMemory((PPSTR) &pDib);
|
|
}
|
|
FreeImgBuf(&pImg);
|
|
*ppDib = pDib;
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: DibFromBitmap()
|
|
|
|
PURPOSE: Will create a global memory block in DIB format that
|
|
represents the Device-dependent bitmap (DDB) passed in.
|
|
|
|
RETURNS: A handle to the DIB
|
|
|
|
****************************************************************************/
|
|
int WINAPI DibFromBitmap (HBITMAP hbm, HPALETTE hpal, PBITMAPINFOHEADER *ppDib){
|
|
|
|
int nStatus = 0;
|
|
|
|
BITMAP bm;
|
|
PBITMAPINFOHEADER pDib;
|
|
HDC hMemDC;
|
|
|
|
|
|
if (hpal == NULL){
|
|
hpal = GetStockObject(DEFAULT_PALETTE);
|
|
}
|
|
|
|
GetObject(hbm, sizeof(BITMAP), (PSTR)&bm);
|
|
|
|
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER) + 1024, (PPSTR) &pDib, ZERO_INIT));
|
|
|
|
pDib->biSize = sizeof(BITMAPINFOHEADER);
|
|
(int) pDib->biWidth = bm.bmWidth;
|
|
(int) pDib->biHeight = bm.bmHeight;
|
|
pDib->biPlanes = 1;
|
|
pDib->biBitCount = bm.bmPlanes * bm.bmBitsPixel;
|
|
pDib->biCompression = BI_RGB;
|
|
pDib->biSizeImage = 0;
|
|
pDib->biXPelsPerMeter = 0;
|
|
pDib->biYPelsPerMeter = 0;
|
|
pDib->biClrUsed = 0;
|
|
pDib->biClrImportant = 0;
|
|
|
|
hMemDC = CreateCompatibleDC(NULL);
|
|
hpal = SelectPalette(hMemDC, hpal, FALSE);
|
|
RealizePalette(hMemDC);
|
|
|
|
// Call GetDIBits with a NULL pBits param, so it will calculate the
|
|
// biSizeImage field for us.
|
|
GetDIBits(hMemDC, hbm, 0, (int) pDib->biHeight, NULL, (PBITMAPINFO) pDib, DIB_RGB_COLORS);
|
|
|
|
// If the driver did not fill in the biSizeImage field, make one up.
|
|
if (pDib->biSizeImage == 0){
|
|
pDib->biSizeImage = (((((DWORD)bm.bmWidth * pDib->biBitCount) + 31 ) / 32) * 4)
|
|
* bm.bmHeight;
|
|
}
|
|
|
|
// Realloc the buffer big enough to hold all the bits.
|
|
CheckError2( ReAllocateMemory(pDib->biSize + PaletteSize(pDib) + pDib->biSizeImage,
|
|
(PPSTR) &pDib, NO_INIT));
|
|
CheckError2( CorrectDibPaletteHdc(hpal, pDib, hMemDC));
|
|
|
|
// Call GetDIBits with a NON-NULL pBits param, and actualy get the
|
|
// bits this time.
|
|
if (!GetDIBits(hMemDC, hbm, 0, (int) pDib->biHeight,
|
|
(PSTR) pDib + pDib->biSize + PaletteSize(pDib),
|
|
(PBITMAPINFO) pDib, DIB_RGB_COLORS)){
|
|
nStatus = Error(DISPLAY_GETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
// This routine is called twice because GetDIBits erases the palette data.
|
|
CheckError2( CorrectDibPaletteHdc(hpal, pDib, hMemDC));
|
|
*ppDib = pDib;
|
|
|
|
|
|
Exit:
|
|
if (nStatus){
|
|
if (pDib){
|
|
FreeMemory((PPSTR) &pDib);
|
|
*ppDib = NULL;
|
|
}
|
|
}
|
|
SelectPalette(hMemDC, hpal, FALSE);
|
|
DeleteDC(hMemDC);
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: PaletteSize(VOID * pv)
|
|
|
|
PURPOSE: Calculates the palette size in bytes. If the info. block
|
|
is of the BITMAPCOREHEADER type, the number of colors is
|
|
multiplied by 3 to give the palette size, otherwise the
|
|
number of colors is multiplied by 4.
|
|
|
|
RETURNS: Palette size in number of bytes.
|
|
|
|
****************************************************************************/
|
|
int WINAPI PaletteSize (VOID * pv){
|
|
|
|
PBITMAPINFOHEADER pDib;
|
|
int NumColors;
|
|
|
|
pDib = (PBITMAPINFOHEADER)pv;
|
|
NumColors = DibNumColors(pDib);
|
|
|
|
if (pDib->biSize == sizeof(BITMAPCOREHEADER)){
|
|
return NumColors * sizeof(RGBTRIPLE);
|
|
}else{
|
|
return NumColors * sizeof(RGBQUAD);
|
|
}
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: DibNumColors
|
|
|
|
PURPOSE: Determines the number of colors in the DIB by looking at
|
|
the BitCount filed in the info block.
|
|
|
|
RETURNS: The number of colors in the DIB.
|
|
|
|
****************************************************************************/
|
|
int WINAPI DibNumColors (VOID * pv){
|
|
|
|
int bits;
|
|
PBITMAPINFOHEADER pDib;
|
|
PBITMAPCOREHEADER pbc;
|
|
|
|
pDib = ((PBITMAPINFOHEADER)pv);
|
|
pbc = ((PBITMAPCOREHEADER)pv);
|
|
|
|
/* With the BITMAPINFO format headers, the size of the palette
|
|
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
|
|
* is dependent on the bits per pixel (= 2 raised to the power of
|
|
* bits/pixel).
|
|
*/
|
|
if (pDib->biSize != sizeof(BITMAPCOREHEADER)){
|
|
if (pDib->biClrUsed != 0)
|
|
return pDib->biClrUsed;
|
|
bits = pDib->biBitCount;
|
|
}else{
|
|
bits = pbc->bcBitCount;
|
|
}
|
|
|
|
switch (bits){
|
|
case 1:
|
|
return 2;
|
|
case 4:
|
|
return 16;
|
|
case 8:
|
|
return 256;
|
|
default:
|
|
/* A 24 bitcount DIB has no color table */
|
|
return 0;
|
|
}
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: IPtoDIB()
|
|
|
|
PURPOSE: Will create a global memory block in DIB format that
|
|
represents the IPpack image passed in.
|
|
|
|
****************************************************************************/
|
|
int WINAPI IPtoDIB(PIMAGE pImage, PIMG pImgSrce, PBITMAPINFOHEADER *ppDib, RECT rRect){
|
|
|
|
int nStatus = 0;
|
|
|
|
int nWidth=0;
|
|
int nWidthBytes;
|
|
int nHeight;
|
|
int nBitsPerPixel;
|
|
int nNumPaletteEntries;
|
|
int nLine;
|
|
PBYTE pAddress;
|
|
PBITMAPINFOHEADER pDib;
|
|
char *hpDib = 0;
|
|
int nLoop;
|
|
int nLeftShiftAmount;
|
|
int nRightShiftAmount;
|
|
int nStartingByte;
|
|
|
|
|
|
if (!pImgSrce){
|
|
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
|
|
goto Exit;
|
|
}
|
|
|
|
nWidth = (rRect.right - rRect.left);
|
|
nHeight = (rRect.bottom - rRect.top);
|
|
|
|
switch (pImgSrce->nType){
|
|
case ITYPE_BI_LEVEL:
|
|
nBitsPerPixel = 1;
|
|
nNumPaletteEntries = 2;
|
|
break;
|
|
|
|
case ITYPE_PAL4:
|
|
case ITYPE_GRAY4:
|
|
nBitsPerPixel = 4;
|
|
nNumPaletteEntries = 16;
|
|
break;
|
|
|
|
case ITYPE_GRAY7:
|
|
nBitsPerPixel = 8;
|
|
nNumPaletteEntries = 128;
|
|
break;
|
|
|
|
case ITYPE_PAL8:
|
|
case ITYPE_CUSPAL8:
|
|
case ITYPE_GRAY8:
|
|
nBitsPerPixel = 8;
|
|
nNumPaletteEntries = 256;
|
|
break;
|
|
|
|
case ITYPE_COMPAL8:
|
|
nBitsPerPixel = 8;
|
|
nNumPaletteEntries = NUMBER_OF_PALETTES;
|
|
break;
|
|
|
|
case ITYPE_RGB24:
|
|
case ITYPE_BGR24:
|
|
nBitsPerPixel = 24;
|
|
nNumPaletteEntries = 0;
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
nStartingByte = (nBitsPerPixel * rRect.left) >> 3;
|
|
|
|
nWidthBytes = (((nWidth * nBitsPerPixel) + 31) / 32) * 4;
|
|
|
|
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER)
|
|
+ (nNumPaletteEntries * 4) + ((ulong)nWidthBytes * nHeight),
|
|
(PPSTR) ppDib, ZERO_INIT));
|
|
pDib = *ppDib;
|
|
|
|
hpDib = (char *) pDib;
|
|
hpDib += sizeof(BITMAPINFOHEADER) + (nNumPaletteEntries * 4);
|
|
|
|
pDib->biSize = sizeof(BITMAPINFOHEADER);
|
|
(int) pDib->biWidth = nWidth;
|
|
(int) pDib->biHeight = nHeight;
|
|
pDib->biPlanes = 1;
|
|
pDib->biBitCount = nBitsPerPixel;
|
|
pDib->biCompression = BI_RGB;
|
|
pDib->biSizeImage = (ulong)nWidthBytes * nHeight;
|
|
pDib->biXPelsPerMeter = 0;
|
|
pDib->biYPelsPerMeter = 0;
|
|
pDib->biClrUsed = nNumPaletteEntries;
|
|
pDib->biClrImportant = nNumPaletteEntries;
|
|
|
|
switch (pImgSrce->nType){
|
|
case ITYPE_BI_LEVEL:
|
|
memset((PSTR) pDib + sizeof(BITMAPINFOHEADER), 0, 8);
|
|
memset((PSTR) pDib + sizeof(BITMAPINFOHEADER) + 4, 0xff, 3);
|
|
break;
|
|
|
|
case ITYPE_PAL4:
|
|
case ITYPE_PAL8:
|
|
case ITYPE_CUSPAL8:
|
|
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR)&pImage->PaletteTable, (pDib->biClrUsed * 4));
|
|
break;
|
|
|
|
case ITYPE_GRAY4:
|
|
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR)&Gray4PaletteTable, (pDib->biClrUsed * 4));
|
|
break;
|
|
|
|
case ITYPE_GRAY7:
|
|
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR)&Gray7PaletteTable, (pDib->biClrUsed * 4));
|
|
break;
|
|
|
|
case ITYPE_GRAY8:
|
|
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR)&Gray8PaletteTable, (pDib->biClrUsed * 4));
|
|
break;
|
|
|
|
case ITYPE_COMPAL8:
|
|
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR)&CommonPaletteTable, (pDib->biClrUsed * 4));
|
|
break;
|
|
|
|
case ITYPE_RGB24:
|
|
case ITYPE_BGR24:
|
|
break;
|
|
}
|
|
|
|
for (nLine = rRect.top; nLine < rRect.bottom; nLine++){
|
|
pAddress = &pImgSrce->bImageData[0] + (nLine * pImgSrce->nBytesPerLine);
|
|
pAddress += nStartingByte;
|
|
|
|
hpDib = ((char *) pDib) + sizeof(BITMAPINFOHEADER) + (nNumPaletteEntries * 4)
|
|
+ (((nHeight - (nLine - rRect.top)) - 1) * nWidthBytes);
|
|
switch (nBitsPerPixel){
|
|
case 1:
|
|
if (!(nLeftShiftAmount = rRect.left & 7)){
|
|
memcpy(hpDib, pAddress, (nWidth + 7) / 8);
|
|
}else{
|
|
nRightShiftAmount = 8 - nLeftShiftAmount;
|
|
for (nLoop = nWidth / 8; nLoop; nLoop--, hpDib++, pAddress++){
|
|
*hpDib = (*pAddress << nLeftShiftAmount)
|
|
| (*(pAddress + 1) >> nRightShiftAmount);
|
|
}
|
|
if ((nWidth & 7)){
|
|
*hpDib = *pAddress << nLeftShiftAmount;
|
|
}
|
|
if ((nWidth & 7) >= nRightShiftAmount){
|
|
*hpDib |= *(pAddress + 1) >> nRightShiftAmount;
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if (rRect.left & 1){
|
|
for (nLoop = nWidth / 2; nLoop; nLoop--, hpDib++, pAddress++){
|
|
*hpDib = (*pAddress << 4) | ((*(pAddress + 1) >> 4) & 0x000f);
|
|
}
|
|
if (nWidth & 1){
|
|
*hpDib = *pAddress << 4;
|
|
}
|
|
}else{
|
|
memcpy(hpDib, pAddress, (nWidth + 1) / 2);
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
case 24:
|
|
if (pImgSrce->nType == ITYPE_RGB24){
|
|
// Convert RGB24 to BGR24.
|
|
for (nLoop = 0; nLoop < nWidth; nLoop++, pAddress += 3){
|
|
*hpDib++ = *(pAddress + 2);
|
|
*hpDib++ = *(pAddress + 1);
|
|
*hpDib++ = *(pAddress + 0);
|
|
}
|
|
}else{
|
|
memcpy(hpDib, pAddress, nWidth * nBitsPerPixel / 8);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: DibToIpNoPal()
|
|
|
|
PURPOSE: Will create an IPpack image for a non-palettized Dib.
|
|
|
|
****************************************************************************/
|
|
int WINAPI DibToIpNoPal(PPIMG ppImg, PBITMAPINFOHEADER pDib){
|
|
|
|
int nStatus = 0;
|
|
|
|
int nWidth=0;
|
|
int nWidthBytes;
|
|
int nWidthBytesIP;
|
|
int nLine;
|
|
int nLines;
|
|
PSTR pAddress;
|
|
char *hpDib;
|
|
int nPixel;
|
|
PIMG pImg;
|
|
int nImageType;
|
|
|
|
|
|
hpDib = (char *) pDib;
|
|
// if the biClrUsed field is 0 and it is not a 24 bit image, then set the palette entries
|
|
// (biClrUsed) field manually
|
|
if (pDib->biClrUsed == 0){
|
|
if (pDib->biBitCount == 1){
|
|
pDib->biClrUsed = 2;
|
|
}
|
|
if (pDib->biBitCount == 4){
|
|
pDib->biClrUsed = 16;
|
|
}
|
|
if (pDib->biBitCount == 8){
|
|
pDib->biClrUsed = 256;
|
|
}
|
|
}
|
|
if (!(nImageType = CheckPalette((LP_FIO_RGBQUAD)
|
|
(hpDib + sizeof(BITMAPINFOHEADER)), pDib->biClrUsed))){
|
|
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
|
|
goto Exit;
|
|
}
|
|
|
|
nWidthBytesIP = ((((int) pDib->biWidth * pDib->biBitCount)
|
|
+ 7) / 8);
|
|
nWidthBytes = (((ulong)nWidthBytesIP + 3) & -4);
|
|
|
|
CheckError2( CreateAnyImgBuf(ppImg, (int) pDib->biWidth, (int) pDib->biHeight, nImageType));
|
|
pImg = *ppImg;
|
|
|
|
nLines = (int) pDib->biHeight;
|
|
|
|
for (nLine = 0; nLine < nLines; nLine++){
|
|
pAddress = &pImg->bImageData[0] + (nLine * pImg->nBytesPerLine);
|
|
if (nImageType == ITYPE_RGB24){
|
|
for (nPixel = 0; nPixel < nWidth; nPixel++){
|
|
*(pAddress + (nPixel * 3)) =
|
|
*(hpDib + sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed * 4)
|
|
+ (((nLines - nLine) - 1) * nWidthBytes)
|
|
+ (nPixel * 3) + 2);
|
|
*(pAddress + (nPixel * 3) + 1) =
|
|
*(hpDib + sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed * 4)
|
|
+ (((nLines - nLine) - 1) * nWidthBytes)
|
|
+ (nPixel * 3) + 1);
|
|
*(pAddress + (nPixel * 3) + 2) =
|
|
*(hpDib + sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed * 4)
|
|
+ (((nLines - nLine) - 1) * nWidthBytes)
|
|
+ (nPixel * 3));
|
|
}
|
|
}else{
|
|
memcpy(pAddress, hpDib + sizeof(BITMAPINFOHEADER)
|
|
+ (pDib->biClrUsed * 4) + (((nLines - nLine) - 1)
|
|
* nWidthBytes), nWidthBytesIP);
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: BWIpToBitmap
|
|
|
|
PURPOSE: Will create a Bitmap from an IPpack image.
|
|
|
|
****************************************************************************/
|
|
int WINAPI BWIpToBitmap (PIMG pImgSrce, PHANDLE phBitmap){
|
|
|
|
int nStatus = 0;
|
|
|
|
BITMAP Bitmap;
|
|
HANDLE hBitmapData = 0;
|
|
char *pBitmapData;
|
|
PSTR pAddress;
|
|
int nLine;
|
|
int nLines;
|
|
int nWidthBytes;
|
|
|
|
|
|
if (!(*phBitmap = CreateBitmap( pImgSrce->nWidth,
|
|
pImgSrce->nHeight, 1, 1, NULL))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if (!GetObject(*phBitmap, sizeof(BITMAP), (PSTR) &Bitmap)){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
nLines = pImgSrce->nHeight;
|
|
nWidthBytes = Bitmap.bmWidthBytes;
|
|
|
|
if (!(hBitmapData = GlobalAlloc(GMEM_MOVEABLE, nLines * nWidthBytes))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if (!(pBitmapData = (PSTR) GlobalLock(hBitmapData))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
|
|
for (nLine = 0; nLine < nLines; nLine++){
|
|
pAddress = &pImgSrce->bImageData[0] + (nLine * pImgSrce->nBytesPerLine);
|
|
memcpy(pBitmapData + (nLine * nWidthBytes),
|
|
pAddress, nWidthBytes);
|
|
}
|
|
|
|
if (!SetBitmapBits(*phBitmap, nLines * nWidthBytes, pBitmapData)){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (nStatus){
|
|
if (*phBitmap){
|
|
DeleteObject(*phBitmap);
|
|
*phBitmap = NULL;
|
|
}
|
|
}
|
|
if (hBitmapData){
|
|
GlobalUnlock(hBitmapData);
|
|
GlobalFree(hBitmapData);
|
|
}
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CorrectDibPalette()
|
|
|
|
PURPOSE: Will correct the palette in the DIB.
|
|
|
|
****************************************************************************/
|
|
int WINAPI CorrectDibPalette(HPALETTE hpal, PBITMAPINFOHEADER pDib){
|
|
|
|
int nStatus = 0;
|
|
|
|
HDC hMemDC;
|
|
|
|
if (hpal == NULL){
|
|
hpal = GetStockObject(DEFAULT_PALETTE);
|
|
}
|
|
|
|
hMemDC = CreateCompatibleDC(NULL);
|
|
hpal = SelectPalette(hMemDC, hpal, FALSE);
|
|
RealizePalette(hMemDC);
|
|
|
|
nStatus = CorrectDibPaletteHdc(hpal, pDib, hMemDC);
|
|
|
|
SelectPalette(hMemDC, hpal, FALSE);
|
|
DeleteDC(hMemDC);
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CorrectDibPaletteHdc()
|
|
|
|
PURPOSE: Will correct the palette in the DIB.
|
|
|
|
****************************************************************************/
|
|
int WINAPI CorrectDibPaletteHdc(HPALETTE hpal, PBITMAPINFOHEADER pDib, HDC hMemDC){
|
|
|
|
int nStatus = 0;
|
|
|
|
char *hpDib;
|
|
int nPal;
|
|
|
|
if (hpal == NULL){
|
|
hpal = GetStockObject(DEFAULT_PALETTE);
|
|
}
|
|
|
|
hpDib = (char *) pDib;
|
|
|
|
if (!pDib->biClrUsed){
|
|
if (pDib->biBitCount == 1){
|
|
pDib->biClrUsed = 2;
|
|
}else if (pDib->biBitCount == 4){
|
|
pDib->biClrUsed = 16;
|
|
}else if (pDib->biBitCount == 8){
|
|
pDib->biClrUsed = 256;
|
|
}else if (pDib->biBitCount == 16){
|
|
pDib->biClrUsed = 32768;
|
|
}else if (pDib->biBitCount == 24){
|
|
pDib->biClrUsed = 0;
|
|
}
|
|
}
|
|
|
|
if (pDib->biClrUsed){
|
|
GetSystemPaletteEntries(hMemDC, 0, pDib->biClrUsed,
|
|
(PPALETTEENTRY)(hpDib + pDib->biSize));
|
|
for (nPal = 0; nPal < (int) pDib->biClrUsed; nPal++){
|
|
*(hpDib + pDib->biSize + (nPal * 4) + 3)
|
|
= *(hpDib + pDib->biSize + (nPal * 4) + 0);
|
|
*(hpDib + pDib->biSize + (nPal * 4) + 0)
|
|
= *(hpDib + pDib->biSize + (nPal * 4) + 2);
|
|
*(hpDib + pDib->biSize + (nPal * 4) + 2)
|
|
= *(hpDib + pDib->biSize + (nPal * 4) + 3);
|
|
*(hpDib + pDib->biSize + (nPal * 4) + 3) = 0;
|
|
}
|
|
}
|
|
|
|
|
|
return(nStatus);
|
|
}
|
|
//
|
|
/****************************************************************************
|
|
|
|
FUNCTION: CheckSelection(PANO_IMAGE pAnoImage, int ACL_flag)
|
|
|
|
PURPOSE: Checks mark selection states to determine which marks
|
|
need to be temporarily selected for the operation
|
|
|
|
****************************************************************************/
|
|
int WINAPI CheckSelection(PANO_IMAGE pAnoImage, int ACL_flag){
|
|
|
|
int nStatus = 0;
|
|
int nMarkIndex;
|
|
int nMarkIndex2;
|
|
PMARK far*ppMarks;
|
|
PMARK pMark;
|
|
PMARK pMark2;
|
|
LRECT lrRect;
|
|
|
|
|
|
ppMarks = pAnoImage->Annotations.ppMarks;
|
|
GetSelectBox (pAnoImage, &lrRect);
|
|
for (nMarkIndex = pAnoImage->Annotations.nMarks -1; nMarkIndex >= 0; nMarkIndex--){
|
|
pMark = ppMarks[nMarkIndex];
|
|
pMark->bTempSelected = FALSE;
|
|
if (!pMark->bSelected && (pMark->Attributes.dwPermissions & ACL_flag)){
|
|
if (lrRect.left < pMark->Attributes.lrBounds.right
|
|
&& lrRect.right > pMark->Attributes.lrBounds.left
|
|
&& lrRect.top < pMark->Attributes.lrBounds.bottom
|
|
&& lrRect.bottom > pMark->Attributes.lrBounds.top){
|
|
pMark->bTempSelected = TRUE;
|
|
continue;
|
|
}
|
|
for (nMarkIndex2 = nMarkIndex; nMarkIndex2 >= 0; nMarkIndex2--){
|
|
pMark2 = ppMarks[nMarkIndex2];
|
|
if (pMark2->bSelected){
|
|
if (pMark2->Attributes.lrBounds.left < pMark->Attributes.lrBounds.right
|
|
&& pMark2->Attributes.lrBounds.right > pMark->Attributes.lrBounds.left
|
|
&& pMark2->Attributes.lrBounds.top < pMark->Attributes.lrBounds.bottom
|
|
&& pMark2->Attributes.lrBounds.bottom > pMark->Attributes.lrBounds.top){
|
|
pMark->bTempSelected = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: OiAnRenderClipboardFormat
|
|
|
|
PURPOSE: To produce the Wang Annotations only or DIB format for
|
|
the clipboard from the Wang Annotations Image format
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI OiAnRenderClipboardFormat(HWND hWnd, UINT uType){
|
|
|
|
int nStatus;
|
|
PWINDOW pWindow;
|
|
PANO_IMAGE pAnoImage;
|
|
PIMAGE pImage;
|
|
|
|
int nType = uType;
|
|
|
|
HANDLE hLocalWangAnnotatedImageFormat;
|
|
HPSTR hpLocalWangAnnotatedImageFormat;
|
|
long lMarksSize;
|
|
PMARK *ppClipboardMarks = 0;
|
|
int nMarks = 0;
|
|
PIMG pDummyImg = 0;
|
|
LRECT lrBounds;
|
|
int nMarkIndex;
|
|
PBITMAPINFOHEADER pDib = 0;
|
|
PMARK pMark;
|
|
int nOldScale;
|
|
long lOldHOff;
|
|
long lOldVOff;
|
|
PAN_IMAGE_STRUCT pAnImage = 0;
|
|
int nLoop;
|
|
int nNamedBlockIndex;
|
|
long lSizeofBlock;
|
|
HANDLE hGDib = 0;
|
|
PBITMAPINFOHEADER pGDib = 0;
|
|
int nHScale;
|
|
int nVScale;
|
|
|
|
|
|
if (nStatus = Init(hWnd, &pWindow, &pAnoImage, FALSE, FALSE)){
|
|
if (nStatus == DISPLAY_IHANDLEINVALID){
|
|
nStatus = 0;
|
|
goto Exit;
|
|
}
|
|
goto Exit;
|
|
}
|
|
pImage = pAnoImage->pBaseImage;
|
|
|
|
if (!(bRenderWangAnnotatedIFormat && (!nType || nType == nWangAnnotatedImageFormat))
|
|
&& !(bRenderWangAnnotations && (!nType || nType == nWangAnnotationFormat))
|
|
&& !(bRenderDib && (!nType || nType == CF_DIB))){
|
|
// Nothing to do.
|
|
goto Exit;
|
|
}
|
|
|
|
/* we always render at full scale */
|
|
CheckError2( TranslateScale(1000, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale));
|
|
|
|
if (nType && nType != CF_DIB && nType != nWangAnnotatedImageFormat
|
|
&& nType != nWangAnnotationFormat){
|
|
nStatus = Error(DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!pAnoImage->pWangAnnotatedImageFormat){
|
|
Error2(DISPLAY_NO_CLIPBOARD); // No data to render, but dont return error
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if ((!nType || nType == nWangAnnotatedImageFormat) && bRenderWangAnnotatedIFormat){
|
|
if (!(hLocalWangAnnotatedImageFormat = GlobalAlloc(GMEM_DDESHARE,
|
|
*((long *) pAnoImage->pWangAnnotatedImageFormat)))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if (!(hpLocalWangAnnotatedImageFormat = GlobalLock(hLocalWangAnnotatedImageFormat))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
memcpy (hpLocalWangAnnotatedImageFormat, pAnoImage->pWangAnnotatedImageFormat,
|
|
*((long *) pAnoImage->pWangAnnotatedImageFormat));
|
|
GlobalUnlock(hLocalWangAnnotatedImageFormat);
|
|
SetClipboardData(nWangAnnotatedImageFormat, hLocalWangAnnotatedImageFormat);
|
|
bRenderWangAnnotatedIFormat = FALSE;
|
|
}
|
|
|
|
if ((!nType || nType == nWangAnnotationFormat) && bRenderWangAnnotations){
|
|
bRenderWangAnnotations = FALSE;
|
|
}
|
|
|
|
if ((!nType || nType == CF_DIB) && bRenderDib){
|
|
lMarksSize = *((long *) pAnoImage->pWangAnnotatedImageFormat);
|
|
CheckError2( AllocateMemory(lMarksSize, (PPSTR) &ppClipboardMarks, ZERO_INIT));
|
|
|
|
memset((PBYTE) ppClipboardMarks, 0, lMarksSize);
|
|
|
|
pAnoImage->hpAnoBlock = pAnoImage->pWangAnnotatedImageFormat;
|
|
pAnoImage->lAnoBlockIndex = 12;
|
|
pAnoImage->lAnoBlockCount = lMarksSize - 12;
|
|
pAnoImage->bAnoBlockUseMemOnly = TRUE;
|
|
CheckError2( ReadAnnotations(hWnd, pAnoImage, &ppClipboardMarks, &nMarks));
|
|
pAnoImage->hpAnoBlock = NULL;
|
|
pAnoImage->lAnoBlockIndex = 0;
|
|
pAnoImage->lAnoBlockCount = 0;
|
|
pAnoImage->bAnoBlockUseMemOnly = 0;
|
|
|
|
if (*ppClipboardMarks == 0){
|
|
// mark might not always exist, example when the application goes away
|
|
// and does not have marks saved in the memory block.
|
|
goto Exit;
|
|
}
|
|
pMark = ppClipboardMarks[0];
|
|
CopyRect (lrBounds, pMark->Attributes.lrBounds);
|
|
for (nMarkIndex = 0; nMarkIndex < nMarks; nMarkIndex++){
|
|
pMark = ppClipboardMarks[nMarkIndex];
|
|
if (((int) pMark->Attributes.uType == OIOP_AN_LINE)
|
|
|| ((int) pMark->Attributes.uType == OIOP_AN_FREEHAND)
|
|
|| ((int) pMark->Attributes.uType == OIOP_AN_HOLLOW_RECT)){
|
|
lrBounds.left = lmin(lrBounds.left,
|
|
pMark->Attributes.lrBounds.left - (((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrBounds.top = lmin(lrBounds.top,
|
|
pMark->Attributes.lrBounds.top - (((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrBounds.right = lmax(lrBounds.right,
|
|
pMark->Attributes.lrBounds.right + (((int) pMark->Attributes.uLineSize + 1)/2));
|
|
lrBounds.bottom = lmax(lrBounds.bottom,
|
|
pMark->Attributes.lrBounds.bottom + (((int) pMark->Attributes.uLineSize + 1)/2));
|
|
}else{
|
|
lrBounds.left = lmin(lrBounds.left, pMark->Attributes.lrBounds.left);
|
|
lrBounds.top = lmin(lrBounds.top, pMark->Attributes.lrBounds.top);
|
|
lrBounds.right = lmax(lrBounds.right, pMark->Attributes.lrBounds.right);
|
|
lrBounds.bottom = lmax(lrBounds.bottom, pMark->Attributes.lrBounds.bottom);
|
|
}
|
|
}
|
|
|
|
// if there is only one mark, and it is an image type then dont call
|
|
// render, which will change the image to 24 bit rgb or bw. Convert it
|
|
// to a dib as is, so that for example if an 8 bit pal image is cut, the
|
|
// data can be pasted back into it
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE && nMarks == 1){
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage));
|
|
|
|
if (!pAnImage){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex
|
|
< pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, szOiDIB, 8)){
|
|
lSizeofBlock = pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
}
|
|
}
|
|
|
|
if (!(hGDib = GlobalAlloc(GHND | GMEM_DDESHARE, lSizeofBlock))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if (!(pGDib = (VOID *) GlobalLock(hGDib))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
memcpy(pGDib, (PSTR) pAnImage, lSizeofBlock);
|
|
GlobalUnlock(hGDib);
|
|
|
|
}else{
|
|
nOldScale = pWindow->nScale;
|
|
pWindow->nScale = 1000;
|
|
lOldHOff = pWindow->lHOffset;
|
|
lOldVOff = pWindow->lVOffset;
|
|
pWindow->lHOffset = 0L;
|
|
pWindow->lVOffset = 0L;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef new
|
|
hDCScreen = GetDC(hWnd);
|
|
|
|
CheckError2( GetDisplayValues(hWnd, pWindow, pImage, &nDisplayPalette, &nDisplayType,
|
|
&nNumberOfPaletteEntries, &hPalette, &bForceBackgroundPalette));
|
|
|
|
if (hPalette){
|
|
hOldPaletteScreen = SelectPalette(hDCScreen, hPalette, bForceBackgroundPalette);
|
|
RealizePalette(hDCScreen);
|
|
}
|
|
|
|
if (!(hDCMemory = CreateCompatibleDC(hDCScreen))){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!(hBitmapMemory = CreateCompatibleBitmap(hDCScreen,
|
|
(int)(lrBounds.right - lrBounds.left),
|
|
(int)(lrBounds.bottom - lrBounds.top)))){
|
|
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
|
|
goto Exit;
|
|
}
|
|
hOldBitmapMemory = SelectObject(hDCMemory, hBitmapMemory);
|
|
|
|
SetLRect(lrTemp, 0, 0, 0, 0);
|
|
SetRRect(rRepaintRect, 0, 0, lrBounds.right - lrBounds.left,
|
|
lrBounds.bottom - lrBounds.top);
|
|
|
|
// Make background area white (image is a mark).
|
|
BitBlt(hDCMemory, 0, 0, rRepaintRect.right, rRepaintRect.bottom,
|
|
NULL, 0, 0, WHITENESS);
|
|
|
|
// Draw annotation stuff here.
|
|
for (nMarkIndex = 0; nMarkIndex < *pnMarks; nMarkIndex++){
|
|
pMark = (*pppMarks)[nMarkIndex];
|
|
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE){
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
|
|
if (pAnRotation && pAnRotation->bFormMark){
|
|
pAnRotation->bClipboardOp = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
CheckError2( PaintAnnotations(hWnd, *phDCMem, pWindow, pImage, *prRepaintRect,
|
|
PaintAnnoFlag, bPaintSelectedWithoutHandles, 1000, nHScale, nVScale, 0, 0,
|
|
&(*pppMarks), &(*pnMarks), OIAN_CLIPBOARD_OPERATION, bUseBilevelDithering,
|
|
DONT_FORCE_OPAQUE_RECTANGLES));
|
|
if (pAnRotation && !pAnRotation->bFormMark){
|
|
pAnRotation->bClipboardOp = FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nStatus = RenderIP (hWnd, NULL, pWindow, pImage, pImage->pImg,
|
|
&pDummyImg, lrBounds, 0, FALSE, SAVE_ANO_ALL, &pDib, TRUE,
|
|
&ppClipboardMarks, &nMarks, nHScale, nVScale)){
|
|
/* restore the actual display scale */
|
|
pWindow->nScale = nOldScale;
|
|
pWindow->lHOffset = lOldHOff;
|
|
pWindow->lVOffset = lOldVOff;
|
|
goto Exit;
|
|
}
|
|
|
|
/* restore the actual display scale */
|
|
pWindow->nScale = nOldScale;
|
|
pWindow->lHOffset = lOldHOff;
|
|
pWindow->lVOffset = lOldVOff;
|
|
|
|
lSizeofBlock = sizeof(BITMAPINFOHEADER) + (pDib->biClrUsed * 4) + pDib->biSizeImage;
|
|
// This must remain GlobalAlloc.
|
|
if (!(hGDib = GlobalAlloc(GHND | GMEM_DDESHARE, lSizeofBlock))){
|
|
nStatus = Error(DISPLAY_CANTALLOC);
|
|
goto Exit;
|
|
}
|
|
if(!(pGDib = (VOID *) GlobalLock(hGDib))){
|
|
nStatus = Error(DISPLAY_CANTLOCK);
|
|
goto Exit;
|
|
}
|
|
memcpy(pGDib, pDib, lSizeofBlock);
|
|
GlobalUnlock(hGDib);
|
|
CheckError2( FreeMemory((PPSTR) &pDib));
|
|
}
|
|
|
|
// Move the data to the clipboard.
|
|
SetClipboardData(CF_DIB, hGDib);
|
|
hGDib = 0;
|
|
bRenderDib = FALSE;
|
|
}
|
|
|
|
|
|
Exit:
|
|
if (ppClipboardMarks){
|
|
// free the local clipboard marks memory
|
|
for (nLoop = nMarks; nLoop; nLoop--){
|
|
pMark = ppClipboardMarks[nLoop - 1];
|
|
DeleteMarkNamedBlocks(pMark);
|
|
FreeMemory((PPSTR) &ppClipboardMarks[nLoop - 1]);
|
|
}
|
|
FreeMemory((PPSTR) ppClipboardMarks);
|
|
}
|
|
if (hGDib){
|
|
GlobalUnlock(hGDib);
|
|
GlobalFree(hGDib);
|
|
}
|
|
|
|
DeInit(FALSE, FALSE);
|
|
return (nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: CreatePartialMark
|
|
|
|
PURPOSE: To create a partial mark based on the ACL bit set to
|
|
must include. It is a new mark which includes only a
|
|
portion of the original mark
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI CreatePartialMark (HWND hWnd, PMARK pNewMarks, PMARK pMark,
|
|
LRECT lrCopyBounds, PINT pnMarks){
|
|
|
|
int nStatus = 0;
|
|
|
|
PAN_POINTS pPoints = 0;
|
|
int nNamedBlockIndex;
|
|
PSTR pBlock;
|
|
LRECT lrRect;
|
|
PWINDOW pWindow;
|
|
PANO_IMAGE pAnoImage;
|
|
PBITMAPINFOHEADER pDib;
|
|
PBITMAPINFOHEADER pDisplayDib;
|
|
PAN_IMAGE_STRUCT pAnImage = 0;
|
|
PAN_IMAGE_STRUCT pDisplayAnImage = 0;
|
|
PAN_IMAGE_STRUCT pNewMarkDisplayAnImage = 0;
|
|
int nWidthBytes;
|
|
int nNewWidthBytes;
|
|
PBITMAPINFOHEADER pNewDib = 0;
|
|
int nLine;
|
|
int nStartLine, nEndLine;
|
|
int nLeft, nRight;
|
|
int nLoop;
|
|
int nShiftLeft, nShiftRight;
|
|
BYTE LeftByte, RightByte;
|
|
int nNewDibLine, nNewDibLoop;
|
|
int nTemp;
|
|
int nRightPixels;
|
|
int nPixelsPerByte;
|
|
PAN_NAME_STRUCT pAnName =0;
|
|
PSTR pFileName;
|
|
HANDLE hdib = 0;
|
|
char FileName[256];
|
|
PAN_NEW_ROTATE_STRUCT pAnRotation = 0;
|
|
PAN_NEW_ROTATE_STRUCT pAnNewMarkRotation = 0;
|
|
|
|
|
|
CheckError2( Init(hWnd, &pWindow, &pAnoImage, FALSE, TRUE));
|
|
memcpy (&pNewMarks[0].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
switch ((int) pMark->Attributes.uType){
|
|
case OIOP_AN_LINE:
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK) * (pNewMarks[0].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[0].nNamedBlocks++;
|
|
}
|
|
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pPoints));
|
|
SetLRect(lrRect, pPoints->ptPoint[0].x + pMark->Attributes.lrBounds.left,
|
|
pPoints->ptPoint[0].y + pMark->Attributes.lrBounds.top,
|
|
pPoints->ptPoint[1].x + pMark->Attributes.lrBounds.left,
|
|
pPoints->ptPoint[1].y + pMark->Attributes.lrBounds.top);
|
|
ConvertRect(pWindow, &lrRect, CONV_FULLSIZE_TO_WINDOW);
|
|
if (ReduceLineToLRect(&lrRect, lrCopyBounds)){
|
|
ConvertRect(pWindow, &lrRect, CONV_WINDOW_TO_FULLSIZE);
|
|
pPoints = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[0], szOiAnoDat,
|
|
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
|
|
pPoints->nMaxPoints = 2;
|
|
pPoints->nPoints = 2;
|
|
|
|
if (lrRect.left < lrRect.right){
|
|
pNewMarks[0].Attributes.lrBounds.left = lrRect.left - lrCopyBounds.left;
|
|
pNewMarks[0].Attributes.lrBounds.right = lrRect.right - lrCopyBounds.left;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.left = lrRect.right - lrCopyBounds.left;
|
|
pNewMarks[0].Attributes.lrBounds.right = lrRect.left - lrCopyBounds.left;
|
|
}
|
|
if (lrRect.top < lrRect.bottom){
|
|
pNewMarks[0].Attributes.lrBounds.top = lrRect.top - lrCopyBounds.top;
|
|
pNewMarks[0].Attributes.lrBounds.bottom = lrRect.bottom - lrCopyBounds.top;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.top = lrRect.bottom - lrCopyBounds.top;
|
|
pNewMarks[0].Attributes.lrBounds.bottom = lrRect.top - lrCopyBounds.top;
|
|
}
|
|
pPoints->ptPoint[0].x = (int) ((lrRect.left - lrCopyBounds.left)
|
|
- pNewMarks[0].Attributes.lrBounds.left);
|
|
pPoints->ptPoint[0].y = (int) ((lrRect.top - lrCopyBounds.top)
|
|
- pNewMarks[0].Attributes.lrBounds.top);
|
|
pPoints->ptPoint[1].x = (int) ((lrRect.right - lrCopyBounds.left)
|
|
- pNewMarks[0].Attributes.lrBounds.left);
|
|
pPoints->ptPoint[1].y = (int) ((lrRect.bottom - lrCopyBounds.top)
|
|
- pNewMarks[0].Attributes.lrBounds.top);
|
|
*pnMarks = 1;
|
|
}
|
|
|
|
break;
|
|
|
|
case OIOP_AN_FILLED_RECT:
|
|
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[0].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, ZERO_INIT));
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[0].nNamedBlocks++;
|
|
}
|
|
|
|
if (pMark->Attributes.lrBounds.left < lrCopyBounds.left){
|
|
pNewMarks[0].Attributes.lrBounds.left = 0;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.left =
|
|
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
|
|
}
|
|
if (pMark->Attributes.lrBounds.right > lrCopyBounds.right){
|
|
pNewMarks[0].Attributes.lrBounds.right =
|
|
lrCopyBounds.right - lrCopyBounds.left;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.right =
|
|
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
|
|
}
|
|
if (pMark->Attributes.lrBounds.top < lrCopyBounds.top){
|
|
pNewMarks[0].Attributes.lrBounds.top = 0;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.top =
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
|
|
}
|
|
if (pMark->Attributes.lrBounds.bottom > lrCopyBounds.bottom){
|
|
pNewMarks[0].Attributes.lrBounds.bottom =
|
|
lrCopyBounds.bottom - lrCopyBounds.top;
|
|
}else{
|
|
pNewMarks[0].Attributes.lrBounds.bottom =
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
|
|
}
|
|
*pnMarks = 1;
|
|
|
|
break;
|
|
|
|
case OIOP_AN_HOLLOW_RECT:
|
|
|
|
*pnMarks = 0;
|
|
// if the hollow rect is wholly contained, then dont break it
|
|
// np into lines, just adjust its bounds
|
|
if (pMark->Attributes.lrBounds.left >= lrCopyBounds.left &&
|
|
pMark->Attributes.lrBounds.right <= lrCopyBounds.right &&
|
|
pMark->Attributes.lrBounds.top >= lrCopyBounds.top &&
|
|
pMark->Attributes.lrBounds.bottom <= lrCopyBounds.bottom){
|
|
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[*pnMarks].nNamedBlocks++;
|
|
}
|
|
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left =
|
|
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.right =
|
|
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top =
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
|
|
|
|
(*pnMarks)++;
|
|
goto Exit; // not an error
|
|
}
|
|
|
|
|
|
if (pMark->Attributes.lrBounds.right <= lrCopyBounds.right){
|
|
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[*pnMarks].nNamedBlocks++;
|
|
}
|
|
|
|
pPoints = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
|
|
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
|
|
pPoints->nMaxPoints = 2;
|
|
pPoints->nPoints = 2;
|
|
|
|
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left =
|
|
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.right =
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top = lmax(0,
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
|
|
lmin(lrCopyBounds.bottom - lrCopyBounds.top,
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
|
|
|
|
pPoints->ptPoint[0].x = 0;
|
|
pPoints->ptPoint[0].y = 0;
|
|
pPoints->ptPoint[1].x = 0;
|
|
pPoints->ptPoint[1].y = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.bottom
|
|
- pNewMarks[*pnMarks].Attributes.lrBounds.top);
|
|
|
|
(*pnMarks)++;
|
|
}
|
|
|
|
if (pMark->Attributes.lrBounds.left >= lrCopyBounds.left){
|
|
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[*pnMarks].nNamedBlocks++;
|
|
}
|
|
|
|
pPoints = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
|
|
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
|
|
pPoints->nMaxPoints = 2;
|
|
pPoints->nPoints = 2;
|
|
|
|
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left =
|
|
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.right =
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top = lmax(0,
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
|
|
lmin(lrCopyBounds.bottom - lrCopyBounds.top,
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
|
|
|
|
pPoints->ptPoint[0].x = 0;
|
|
pPoints->ptPoint[0].y = 0;
|
|
pPoints->ptPoint[1].x = 0;
|
|
pPoints->ptPoint[1].y = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.bottom
|
|
- pNewMarks[*pnMarks].Attributes.lrBounds.top);
|
|
|
|
(*pnMarks)++;
|
|
}
|
|
|
|
if (pMark->Attributes.lrBounds.bottom <= lrCopyBounds.bottom){
|
|
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex <
|
|
pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[*pnMarks].nNamedBlocks++;
|
|
}
|
|
|
|
pPoints = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
|
|
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
|
|
pPoints->nMaxPoints = 2;
|
|
pPoints->nPoints = 2;
|
|
|
|
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left =
|
|
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.right =
|
|
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
|
|
lrCopyBounds.right - lrCopyBounds.left);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top =
|
|
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top;
|
|
|
|
pPoints->ptPoint[0].x = 0;
|
|
pPoints->ptPoint[0].y = 0;
|
|
pPoints->ptPoint[1].x = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.right
|
|
- pNewMarks[*pnMarks].Attributes.lrBounds.left);
|
|
pPoints->ptPoint[1].y = 0;
|
|
|
|
(*pnMarks)++;
|
|
}
|
|
if (pMark->Attributes.lrBounds.top >= lrCopyBounds.top){
|
|
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
|
|
sizeof(OIAN_MARK_ATTRIBUTES));
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex <
|
|
pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[*pnMarks].nNamedBlocks++;
|
|
}
|
|
|
|
pPoints = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
|
|
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
|
|
pPoints->nMaxPoints = 2;
|
|
pPoints->nPoints = 2;
|
|
|
|
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left =
|
|
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.right =
|
|
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
|
|
lrCopyBounds.right - lrCopyBounds.left);
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top =
|
|
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.top;
|
|
|
|
pPoints->ptPoint[0].x = 0;
|
|
pPoints->ptPoint[0].y = 0;
|
|
pPoints->ptPoint[1].x = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.right -
|
|
pNewMarks[*pnMarks].Attributes.lrBounds.left);
|
|
pPoints->ptPoint[1].y = 0;
|
|
|
|
(*pnMarks)++;
|
|
}
|
|
break;
|
|
case OIOP_AN_TEXT:
|
|
case OIOP_AN_TEXT_FROM_A_FILE:
|
|
case OIOP_AN_TEXT_STAMP:
|
|
case OIOP_AN_ATTACH_A_NOTE:
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex <
|
|
pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK) * (pNewMarks[0].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[0].nNamedBlocks++;
|
|
}
|
|
// set text rect to a filled rect the color of the background
|
|
pNewMarks[0].Attributes.uType = OIOP_AN_FILLED_RECT;
|
|
pNewMarks[0].Attributes.lrBounds.left =
|
|
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
|
|
pNewMarks[0].Attributes.lrBounds.right = lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
|
|
lrCopyBounds.right - lrCopyBounds.left);
|
|
pNewMarks[0].Attributes.lrBounds.top = lmax(0, pMark->Attributes.lrBounds.top - lrCopyBounds.top);
|
|
pNewMarks[0].Attributes.lrBounds.bottom = lmin(pMark->Attributes.lrBounds.bottom - lrCopyBounds.top,
|
|
lrCopyBounds.bottom - lrCopyBounds.top);
|
|
(*pnMarks)++;
|
|
break;
|
|
|
|
case OIOP_AN_IMAGE:
|
|
case OIOP_AN_IMAGE_BY_REFERENCE:
|
|
case OIOP_AN_FORM:
|
|
//copy all named blocks from old mark to new mark
|
|
for (nNamedBlockIndex = 0; nNamedBlockIndex <
|
|
pMark->nNamedBlocks; nNamedBlockIndex++){
|
|
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
|
|
* (pNewMarks[0].nNamedBlocks + 1),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
|
|
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
|
|
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
|
|
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
|
|
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
|
|
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
|
|
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
|
|
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
|
|
|
|
pNewMarks[0].nNamedBlocks++;
|
|
}
|
|
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;
|
|
}
|
|
pFileName = FileName;
|
|
GetFileName (pFileName, (PSTR) pAnName->name);
|
|
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));
|
|
}else{
|
|
pDib = (PBITMAPINFOHEADER) pAnImage;
|
|
}
|
|
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage));
|
|
if (!pDisplayAnImage){
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
|
|
if (pAnRotation == 0){
|
|
nStatus = Error (DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
|
|
CheckError2( ConvResolutionAnoBitmap(hWnd, pMark, pAnRotation->rotation, OI_SCALE_ALG_NORMAL));
|
|
CheckError2( GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage));
|
|
}
|
|
pDisplayDib = (PBITMAPINFOHEADER) pDisplayAnImage;
|
|
pNewMarks[0].Attributes.lrBounds.left =
|
|
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
|
|
pNewMarks[0].Attributes.lrBounds.right =
|
|
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
|
|
lrCopyBounds.right - lrCopyBounds.left);
|
|
pNewMarks[0].Attributes.lrBounds.top =
|
|
lmax(0, pMark->Attributes.lrBounds.top - lrCopyBounds.top);
|
|
pNewMarks[0].Attributes.lrBounds.bottom =
|
|
lmin(pMark->Attributes.lrBounds.bottom - lrCopyBounds.top,
|
|
lrCopyBounds.bottom - lrCopyBounds.top);
|
|
|
|
nWidthBytes = ((((pMark->Attributes.lrBounds.right
|
|
- pMark->Attributes.lrBounds.left) * pDisplayDib->biBitCount) + 31) / 32) * 4;
|
|
|
|
nNewWidthBytes = ((((pNewMarks[0].Attributes.lrBounds.right
|
|
- pNewMarks[0].Attributes.lrBounds.left) * pDisplayDib->biBitCount) + 31) / 32) * 4;
|
|
|
|
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER)
|
|
+ (pDisplayDib->biClrUsed * 4) + (nNewWidthBytes *
|
|
(pNewMarks[0].Attributes.lrBounds.bottom
|
|
- pNewMarks[0].Attributes.lrBounds.top)), (PPSTR) &pNewDib, ZERO_INIT));
|
|
|
|
pNewDib->biSize = sizeof(BITMAPINFOHEADER);
|
|
pNewDib->biWidth = pNewMarks[0].Attributes.lrBounds.right -
|
|
pNewMarks[0].Attributes.lrBounds.left;
|
|
pNewDib->biHeight = pNewMarks[0].Attributes.lrBounds.bottom -
|
|
pNewMarks[0].Attributes.lrBounds.top;
|
|
pNewDib->biPlanes = 1;
|
|
pNewDib->biBitCount = pDisplayDib->biBitCount;
|
|
pNewDib->biCompression = BI_RGB;
|
|
pNewDib->biSizeImage = nNewWidthBytes *
|
|
(pNewMarks[0].Attributes.lrBounds.bottom -
|
|
pNewMarks[0].Attributes.lrBounds.top);
|
|
pNewDib->biXPelsPerMeter = 0;
|
|
pNewDib->biYPelsPerMeter = 0;
|
|
pNewDib->biClrUsed = pDisplayDib->biClrUsed;
|
|
pNewDib->biClrImportant = pDisplayDib->biClrImportant;
|
|
|
|
// copy the palette to the new dib
|
|
memcpy((PSTR) pNewDib + sizeof(BITMAPINFOHEADER),
|
|
(PSTR) pDisplayDib + sizeof(BITMAPINFOHEADER),
|
|
(pDisplayDib->biClrUsed * 4));
|
|
nStartLine = (int) lmax(0, lrCopyBounds.top - pMark->Attributes.lrBounds.top);
|
|
nEndLine = (int) lmin(pMark->Attributes.lrBounds.bottom
|
|
- lmax(lrCopyBounds.top, pMark->Attributes.lrBounds.top),
|
|
lrCopyBounds.bottom - lmax(lrCopyBounds.top,
|
|
pMark->Attributes.lrBounds.top)) + nStartLine;
|
|
// now adjust for the fact that dibs are stored npside down
|
|
nTemp = nStartLine;
|
|
nStartLine = (int)(pDisplayDib->biHeight - nEndLine);
|
|
nEndLine = (int)(pDisplayDib->biHeight - nTemp);
|
|
|
|
nLeft = (int)lmax(0, lrCopyBounds.left - pMark->Attributes.lrBounds.left);
|
|
nRight = (int)lmin(pMark->Attributes.lrBounds.right
|
|
- lmax(lrCopyBounds.left, pMark->Attributes.lrBounds.left),
|
|
lrCopyBounds.right - lmax(lrCopyBounds.left, pMark->Attributes.lrBounds.left)) + nLeft;
|
|
// set shift bits according to image type
|
|
if (pDisplayDib->biBitCount == 1){
|
|
nShiftLeft = nLeft & 7;
|
|
nShiftRight = 8 - nShiftLeft;
|
|
}
|
|
if (pDisplayDib->biBitCount == 4){
|
|
nShiftLeft = nLeft & 1;
|
|
if (nShiftLeft){ // need to shift by 4 bits
|
|
nShiftLeft = 4;
|
|
nShiftRight = 4;
|
|
}else{
|
|
nShiftLeft = 0;
|
|
nShiftRight = 8;
|
|
}
|
|
}
|
|
// save value of nRight in pixels in case nRight changes
|
|
nRightPixels = nRight;
|
|
// adjust nLeft and nRight from pixels to bytes
|
|
if (pDisplayDib->biBitCount == 1){
|
|
nPixelsPerByte = 8;
|
|
}
|
|
if (pDisplayDib->biBitCount == 4){
|
|
nPixelsPerByte = 2;
|
|
}
|
|
if ((pDisplayDib->biBitCount == 1) || (pDisplayDib->biBitCount == 4)){
|
|
nLeft = nLeft / nPixelsPerByte;
|
|
nRight = nRight / nPixelsPerByte;
|
|
}
|
|
if (pDisplayDib->biBitCount == 24){
|
|
nLeft = nLeft * 3;
|
|
nRight = nRight * 3;
|
|
}
|
|
switch (pDisplayDib->biBitCount){
|
|
case 1: //black and white
|
|
case 4: // 4 bits per pixel
|
|
for (nLine = nStartLine, nNewDibLine = 0; nLine < nEndLine;
|
|
nLine++, nNewDibLine++){
|
|
for (nLoop = nLeft, nNewDibLoop=0; nLoop <= nRight;
|
|
nLoop++, nNewDibLoop++){
|
|
LeftByte = *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER) +
|
|
(pDisplayDib->biClrUsed * 4) + ((ulong)nWidthBytes *
|
|
nLine) + nLoop) << nShiftLeft;
|
|
if ((nLoop * nPixelsPerByte) + nShiftLeft <= nRightPixels){
|
|
RightByte = *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER) +
|
|
(pDisplayDib->biClrUsed * 4)
|
|
+ ((ulong)nWidthBytes * nLine) + nLoop +1)
|
|
>> nShiftRight;
|
|
*((BYTE *) pNewDib + sizeof(BITMAPINFOHEADER)+
|
|
(pDisplayDib->biClrUsed * 4) + ((ulong)nNewWidthBytes *
|
|
nNewDibLine) + nNewDibLoop) = LeftByte | RightByte;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
case 24:
|
|
for (nLine = nStartLine, nNewDibLine = 0; nLine < nEndLine;
|
|
nLine++, nNewDibLine++){
|
|
for (nLoop = nLeft, nNewDibLoop=0; nLoop < nRight;
|
|
nLoop++, nNewDibLoop++){
|
|
*((BYTE *) pNewDib + sizeof(BITMAPINFOHEADER)+
|
|
(pDisplayDib->biClrUsed * 4) + ((ulong)nNewWidthBytes
|
|
* nNewDibLine) + nNewDibLoop)
|
|
= *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER)
|
|
+ (pDisplayDib->biClrUsed * 4) + ((ulong)nWidthBytes * nLine) + nLoop);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_DATACORRUPTED);
|
|
goto Exit;
|
|
}
|
|
CheckError2( GetAMarkNamedBlock(&pNewMarks[0], szOiZDpDIB,
|
|
(PPSTR) &pNewMarkDisplayAnImage));
|
|
if (pNewMarkDisplayAnImage){
|
|
CheckError2( DeleteAMarkNamedBlock (&pNewMarks[0], szOiZDpDIB));
|
|
}
|
|
pNewMarkDisplayAnImage = 0;
|
|
CheckError2( AddAMarkNamedBlock(&pNewMarks[0], szOiDIB,
|
|
(PPSTR) &pNewMarkDisplayAnImage, sizeof(BITMAPINFOHEADER)
|
|
+ (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage)));
|
|
|
|
memcpy (pNewMarkDisplayAnImage->dibInfo, pNewDib,
|
|
sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage));
|
|
|
|
CheckError2( GetAMarkNamedBlock(&pNewMarks[0], szOiAnoDat,
|
|
(PPSTR) &pAnNewMarkRotation));
|
|
// partial marks cannot be converted back to form or image by
|
|
// reference marks
|
|
if (pAnNewMarkRotation && pAnNewMarkRotation->bFormMark){
|
|
pAnNewMarkRotation->bFormMark = FALSE;
|
|
pAnNewMarkRotation->bClipboardOp = FALSE;
|
|
}
|
|
(*pnMarks)++;
|
|
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
FreeMemory((PPSTR) &pDib);
|
|
FreeMemory((PPSTR) &pNewDib);
|
|
|
|
DeInit(FALSE, TRUE);
|
|
return (nStatus);
|
|
}
|
|
//
|
|
/*****************************************************************************
|
|
|
|
FUNCTION: CopyImageIDK
|
|
|
|
PURPOSE: Copys a piece of an image from 1 buffer to another.
|
|
rSourceRect = source rectangle (including width and height).
|
|
rDestRect.left,top = npper left of dest rect.
|
|
rDestRect.right,bottom = ignored (modified to be correct).
|
|
|
|
*****************************************************************************/
|
|
|
|
int WINAPI CopyImageIDK(PIMG pSourceImg, PIMG pDestImg, RECT rSourceRect,
|
|
RECT rDestRect){
|
|
|
|
int nStatus = 0;
|
|
|
|
int nWidth=0;
|
|
int nHeight;
|
|
int nSourceLine;
|
|
int nLastSourceLine;
|
|
PBYTE pSourceLine;
|
|
int nDestLine;
|
|
PBYTE pDestLine;
|
|
BYTE cDestByte;
|
|
int nLoop;
|
|
|
|
int nPixels;
|
|
int nBitsPerPixel;
|
|
|
|
BOOL bTopToBottom;
|
|
BOOL bLeftToRight;
|
|
|
|
BYTE cLeftShift;
|
|
BYTE cRightShift;
|
|
|
|
BYTE cFirstDestMask;
|
|
int nFirstSourceByte;
|
|
int nFirstDestByte;
|
|
BOOL bDoFirstLeftShift = FALSE;
|
|
BOOL bDoFirstRightShift = FALSE;
|
|
|
|
int nMiddleBytes;
|
|
|
|
BOOL bDoLastLeftShift = FALSE;
|
|
BOOL bDoLastRightShift = FALSE;
|
|
BYTE cLastDestMask;
|
|
|
|
|
|
if (!pSourceImg){
|
|
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (rSourceRect.bottom <= rSourceRect.top || rSourceRect.right <= rSourceRect.left
|
|
|| rSourceRect.top < 0 || rSourceRect.left < 0
|
|
|| rDestRect.top < 0 || rDestRect.left < 0){
|
|
nStatus = Error(DISPLAY_INVALIDRECT);
|
|
goto Exit;
|
|
}
|
|
if (pSourceImg->nType != pDestImg->nType){
|
|
nStatus = Error(DISPLAY_INVALID_OPTIONS);
|
|
goto Exit;
|
|
}
|
|
|
|
nWidth = rSourceRect.right - rSourceRect.left;
|
|
nHeight = rSourceRect.bottom - rSourceRect.top;
|
|
rDestRect.right = rDestRect.left + nWidth;
|
|
rDestRect.bottom = rDestRect.top + nHeight;
|
|
|
|
switch (pSourceImg->nType){
|
|
case ITYPE_BI_LEVEL:
|
|
nBitsPerPixel = 1;
|
|
switch (nWidth){
|
|
case 1: cFirstDestMask = 0x80; break;
|
|
case 2: cFirstDestMask = 0xc0; break;
|
|
case 3: cFirstDestMask = 0xe0; break;
|
|
case 4: cFirstDestMask = 0xf0; break;
|
|
case 5: cFirstDestMask = 0xf8; break;
|
|
case 6: cFirstDestMask = 0xfc; break;
|
|
case 7: cFirstDestMask = 0xfe; break;
|
|
default: cFirstDestMask = 0xff; break;
|
|
}
|
|
cFirstDestMask >>= rDestRect.left & 7;
|
|
|
|
if ((rSourceRect.left & 7) >= (rDestRect.left & 7)){
|
|
cLeftShift = (rSourceRect.left & 7) - (rDestRect.left & 7);
|
|
}else{
|
|
cLeftShift = (8 + (rSourceRect.left & 7)) - (rDestRect.left & 7);
|
|
}
|
|
cRightShift = 8 - cLeftShift;
|
|
|
|
if (!cLeftShift || (rDestRect.left & 7) < cRightShift){
|
|
bDoFirstLeftShift = TRUE;
|
|
}
|
|
if (cLeftShift && ((rDestRect.left & 7) + nWidth) > cRightShift){
|
|
bDoFirstRightShift = TRUE;
|
|
}
|
|
|
|
nPixels = nWidth;
|
|
nPixels -= min(nWidth, 8 - (rDestRect.left & 7));
|
|
nMiddleBytes = nPixels >> 3;
|
|
nPixels &= 7;
|
|
|
|
if (nPixels){
|
|
bDoLastLeftShift = TRUE;
|
|
if (nPixels > cRightShift){
|
|
bDoLastRightShift = TRUE;
|
|
}
|
|
}
|
|
|
|
switch (nPixels){
|
|
case 1: cLastDestMask = 0x80; break;
|
|
case 2: cLastDestMask = 0xc0; break;
|
|
case 3: cLastDestMask = 0xe0; break;
|
|
case 4: cLastDestMask = 0xf0; break;
|
|
case 5: cLastDestMask = 0xf8; break;
|
|
case 6: cLastDestMask = 0xfc; break;
|
|
case 7: cLastDestMask = 0xfe; break;
|
|
default: cLastDestMask = 0x00; break;
|
|
}
|
|
break;
|
|
|
|
case ITYPE_GRAY4:
|
|
case ITYPE_PAL4:
|
|
nBitsPerPixel = 4;
|
|
if (nWidth > 1){
|
|
cFirstDestMask = 0xff;
|
|
}else{
|
|
cFirstDestMask = 0xf0;
|
|
}
|
|
if (rDestRect.left & 1){
|
|
cFirstDestMask >>= 4;
|
|
}
|
|
|
|
if ((rSourceRect.left & 1) != (rDestRect.left & 1)){
|
|
cLeftShift = 4;
|
|
}else{
|
|
cLeftShift = 0;
|
|
}
|
|
cRightShift = 8 - cLeftShift;
|
|
|
|
nPixels = nWidth;
|
|
if ((rDestRect.left & 1) || nWidth == 1){
|
|
if ((rSourceRect.left & 1) || !(rDestRect.left & 1)){
|
|
bDoFirstLeftShift = TRUE;
|
|
}else{
|
|
bDoFirstRightShift = TRUE;
|
|
}
|
|
nPixels--;
|
|
}
|
|
|
|
nMiddleBytes = nPixels >> 1;
|
|
nPixels &= 1;
|
|
|
|
if (nPixels){
|
|
bDoLastLeftShift = TRUE;
|
|
cLastDestMask = 0xf0;
|
|
}
|
|
break;
|
|
|
|
case ITYPE_GRAY7:
|
|
case ITYPE_GRAY8:
|
|
case ITYPE_CUSPAL8:
|
|
case ITYPE_COMPAL8:
|
|
nBitsPerPixel = 8;
|
|
cLeftShift = 0;
|
|
cRightShift = 0;
|
|
nMiddleBytes = nWidth;
|
|
break;
|
|
|
|
case ITYPE_RGB24:
|
|
case ITYPE_BGR24:
|
|
nBitsPerPixel = 24;
|
|
cLeftShift = 0;
|
|
cRightShift = 0;
|
|
nMiddleBytes = nWidth * 3;
|
|
break;
|
|
|
|
default:
|
|
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (pSourceImg != pDestImg || rSourceRect.top >= rDestRect.top){
|
|
bTopToBottom = TRUE;
|
|
nDestLine = rDestRect.top;
|
|
nSourceLine = rSourceRect.top;
|
|
nLastSourceLine = rSourceRect.bottom - 1;
|
|
}else{
|
|
bTopToBottom = FALSE;
|
|
nDestLine = rDestRect.bottom - 1;
|
|
nSourceLine = rSourceRect.bottom - 1;
|
|
nLastSourceLine = rSourceRect.top;
|
|
}
|
|
if (pSourceImg != pDestImg || rSourceRect.left >= rDestRect.left
|
|
|| rSourceRect.top != rDestRect.top){
|
|
bLeftToRight = TRUE;
|
|
nFirstSourceByte = (rSourceRect.left * nBitsPerPixel) >> 3;
|
|
nFirstDestByte = (rDestRect.left * nBitsPerPixel) >> 3;
|
|
}else{
|
|
bLeftToRight = FALSE;
|
|
nFirstSourceByte = ((rSourceRect.right * nBitsPerPixel) - 1) >> 3;
|
|
nFirstDestByte = ((rDestRect.right * nBitsPerPixel) - 1) >> 3;
|
|
}
|
|
|
|
|
|
while(1){
|
|
pSourceLine = &pSourceImg->bImageData[0] + (nSourceLine * pSourceImg->nBytesPerLine);
|
|
pDestLine = &pDestImg->bImageData[0] + (nDestLine * pDestImg->nBytesPerLine);
|
|
|
|
pSourceLine += nFirstSourceByte;
|
|
pDestLine += nFirstDestByte;
|
|
|
|
if (bLeftToRight){
|
|
// Do first byte
|
|
cDestByte = 0;
|
|
if (bDoFirstLeftShift){
|
|
cDestByte = *(pSourceLine++) << cLeftShift;
|
|
}
|
|
if (bDoFirstRightShift){
|
|
cDestByte |= *pSourceLine >> cRightShift;
|
|
}
|
|
if (bDoFirstLeftShift || bDoFirstRightShift){
|
|
*pDestLine = (*pDestLine & ~cFirstDestMask) | (cDestByte & cFirstDestMask);
|
|
pDestLine++;
|
|
}
|
|
|
|
// Do middle bytes?
|
|
if (nMiddleBytes){
|
|
if (!cLeftShift){
|
|
memcpy(pDestLine, pSourceLine, nMiddleBytes);
|
|
pDestLine += nMiddleBytes;
|
|
pSourceLine += nMiddleBytes;
|
|
}else{
|
|
for (nLoop = nMiddleBytes; nLoop; nLoop--){
|
|
cDestByte = *(pSourceLine++) << cLeftShift;
|
|
*(pDestLine++) = cDestByte | (*pSourceLine >> cRightShift);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Do last byte?
|
|
if (bDoLastLeftShift){
|
|
cDestByte = *(pSourceLine++) << cLeftShift;
|
|
if (bDoLastRightShift){
|
|
cDestByte |= *pSourceLine >> cRightShift;
|
|
}
|
|
*pDestLine = (*pDestLine & ~cLastDestMask) | (cDestByte & cLastDestMask);
|
|
}
|
|
}else{ // Right to left.
|
|
// Do last byte?
|
|
cDestByte = 0;
|
|
if (bDoLastRightShift){
|
|
cDestByte = *(pSourceLine--) >> cRightShift;
|
|
}
|
|
if (bDoLastLeftShift){
|
|
cDestByte |= *pSourceLine << cLeftShift;
|
|
}
|
|
if (bDoLastLeftShift || bDoLastRightShift){
|
|
*(pDestLine--) = (*pDestLine & ~cLastDestMask) | (cDestByte & cLastDestMask);
|
|
if (!cLeftShift){
|
|
--pSourceLine;
|
|
}
|
|
}
|
|
|
|
// Do middle bytes?
|
|
if (nMiddleBytes){
|
|
if (!cLeftShift){
|
|
for (nLoop = nMiddleBytes; nLoop; nLoop--){
|
|
*(pDestLine--) = *(pSourceLine--);
|
|
}
|
|
}else{
|
|
for (nLoop = nMiddleBytes; nLoop; nLoop--){
|
|
cDestByte = *(pSourceLine--) >> cRightShift;
|
|
*(pDestLine--) = cDestByte | (*pSourceLine << cLeftShift);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Do first byte
|
|
if (bDoFirstRightShift || bDoFirstLeftShift){
|
|
cDestByte = 0;
|
|
if (bDoFirstRightShift){
|
|
cDestByte = *(pSourceLine--) >> cRightShift;
|
|
}
|
|
if (bDoFirstLeftShift){
|
|
cDestByte |= *pSourceLine << cLeftShift;
|
|
}
|
|
*pDestLine = (*pDestLine & ~cFirstDestMask) | (cDestByte & cFirstDestMask);
|
|
}
|
|
}
|
|
|
|
if (nSourceLine == nLastSourceLine){
|
|
break;
|
|
}
|
|
|
|
if (bTopToBottom){
|
|
nDestLine++;
|
|
nSourceLine++;
|
|
}else{
|
|
nDestLine--;
|
|
nSourceLine--;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
return(nStatus);
|
|
}
|