|
|
#include "stdafx.h"
#include "global.h"
#include "pbrush.h"
#include "pbrusdoc.h"
#include "pbrusfrm.h"
#include "pbrusvw.h"
#include "minifwnd.h"
#include "bmobject.h"
#include "imgsuprt.h"
#include "imgwnd.h"
#include "imgbrush.h"
#include "imgwell.h"
#include "imgtools.h"
#include "t_fhsel.h"
#include "toolbox.h"
#include "mmsystem.h"
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif
#include "memtrace.h"
CImgBrush theImgBrush;
CImgBrush::CImgBrush() : m_bCuttingFromImage(FALSE), m_bOpaque(TRUE) { }
CImgBrush::~CImgBrush() { // cleanup old region if exists
if (m_cRgnPolyFreeHandSel.GetSafeHandle() != NULL) m_cRgnPolyFreeHandSel.DeleteObject();
if (m_cRgnPolyFreeHandSelBorder.GetSafeHandle() != NULL) m_cRgnPolyFreeHandSelBorder.DeleteObject();
if (m_hbmOld) m_dc.SelectObject( CBitmap::FromHandle( m_hbmOld ) );
if (m_hbmMaskOld) m_dc.SelectObject( CBitmap::FromHandle( m_hbmMaskOld ) );
m_dc.DeleteDC(); m_bitmap.DeleteObject(); m_maskDC.DeleteDC(); m_maskBitmap.DeleteObject(); }
BOOL CImgBrush::CopyTo(CImgBrush& destBrush) { if (destBrush.m_hbmOld) destBrush.m_dc.SelectObject( CBitmap::FromHandle( destBrush.m_hbmOld ) );
if (destBrush.m_hbmMaskOld) destBrush.m_maskDC.SelectObject( CBitmap::FromHandle( destBrush.m_hbmMaskOld ) );
destBrush.m_hbmOld = NULL; destBrush.m_hbmMaskOld = NULL;
destBrush.m_dc.DeleteDC(); destBrush.m_bitmap.DeleteObject(); destBrush.m_maskDC.DeleteDC(); destBrush.m_maskBitmap.DeleteObject();
if (m_dc.m_hDC != NULL) { if (! destBrush.m_dc.CreateCompatibleDC( NULL ) || ! destBrush.m_bitmap.CreateCompatibleBitmap(&m_dc, m_size.cx, m_size.cy)) { theApp.SetGdiEmergency(FALSE); return FALSE; }
destBrush.m_hbmOld = (HBITMAP)((destBrush.m_dc.SelectObject( &destBrush.m_bitmap ))->GetSafeHandle());
CPalette* ppalOldSrc = SetBrushPalette( &m_dc, TRUE ); // Background ??
CPalette* ppalOldDest = SetBrushPalette( &destBrush.m_dc, TRUE ); // Background ??
destBrush.m_dc.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, SRCCOPY );
if (ppalOldSrc) m_dc.SelectPalette( ppalOldSrc, TRUE ); // Background ??
if (ppalOldDest) destBrush.m_dc.SelectPalette( ppalOldDest, TRUE ); // Background ??
}
if (m_maskDC.m_hDC != NULL) { if (! destBrush.m_maskDC.CreateCompatibleDC(NULL) || ! destBrush.m_maskBitmap.CreateCompatibleBitmap(&m_maskDC, m_size.cx, m_size.cy)) { theApp.SetGdiEmergency(FALSE); return FALSE; }
destBrush.m_hbmMaskOld = (HBITMAP)((destBrush.m_maskDC.SelectObject( &destBrush.m_maskBitmap))->GetSafeHandle()); destBrush.m_maskDC.BitBlt(0, 0, m_size.cx, m_size.cy, &m_maskDC, 0, 0, SRCCOPY); }
destBrush.m_size = m_size; destBrush.m_bFirstDrag = m_bFirstDrag; destBrush.m_bLastDragWasASmear = m_bLastDragWasASmear; destBrush.m_bLastDragWasFirst = m_bLastDragWasFirst; destBrush.m_bMakingSelection = m_bMakingSelection; destBrush.m_bMoveSel = m_bMoveSel; destBrush.m_bSmearSel = m_bSmearSel; destBrush.m_bOpaque = m_bOpaque; destBrush.m_rcDraggedFrom = m_rcDraggedFrom; destBrush.m_pImg = m_pImg; destBrush.m_rcSelection = m_rcSelection; destBrush.m_handle = m_handle;
return TRUE; }
void CImgBrush::CenterHandle() { m_handle.cx = m_size.cx / 2; m_handle.cy = m_size.cy / 2; }
void CImgBrush::TopLeftHandle() { m_handle.cx = 0; m_handle.cy = 0; }
CPalette* CImgBrush::SetBrushPalette( CDC* pdc, BOOL bForce ) { CPalette* ppal = NULL; CPalette* ppalOld = NULL;
if (theApp.m_pPalette && theApp.m_pPalette->m_hObject) ppal = theApp.m_pPalette;
if (ppal != NULL) { ppalOld = pdc->SelectPalette( ppal, bForce );
pdc->RealizePalette(); } return ppalOld; }
HPALETTE CImgBrush::SetBrushPalette( HDC hdc, BOOL bForce ) { CPalette* ppal = NULL; HPALETTE hpalOld = NULL;
if (theApp.m_pPalette && theApp.m_pPalette->m_hObject) ppal = theApp.m_pPalette;
if (ppal != NULL) { hpalOld = ::SelectPalette( hdc, (HPALETTE)ppal->m_hObject, bForce );
RealizePalette( hdc ); } return hpalOld; }
BOOL CImgBrush::SetSize( CSize newSize, BOOL bStretchToFit ) { BOOL bFlipX; BOOL bFlipY;
if (newSize.cx == m_size.cx && newSize.cy == m_size.cy) return TRUE;
if (bFlipX = (newSize.cx < 0)) newSize.cx = -newSize.cx;
if (bFlipY = (newSize.cy < 0)) newSize.cy = -newSize.cy;
if (newSize.cx == 0) newSize.cx = 1;
if (newSize.cy == 0) newSize.cy = 1;
if (CImgTool::GetCurrentID() != IDMX_TEXTTOOL) { CDC newDC; CBitmap newBitmap; CDC newMaskDC; CBitmap newMaskBitmap;
//REARCHITECT Potential for DC && Bitmap leaks here on partial failure!!
if (! newDC.CreateCompatibleDC ( &m_dc ) || ! newBitmap.CreateCompatibleBitmap( &m_dc, newSize.cx, newSize.cy ) || ! newMaskDC.CreateCompatibleDC ( &m_dc ) || ! newMaskBitmap.CreateBitmap(newSize.cx, newSize.cy, 1, 1, NULL )) return FALSE;
CBitmap* pbmOld = newDC.SelectObject( &newBitmap ); CPalette* ppalOldSrc = SetBrushPalette( &m_dc, FALSE ); CPalette* ppalOldDest = SetBrushPalette( &newDC, FALSE );
newDC.SetStretchBltMode(COLORONCOLOR);
if (bStretchToFit) { StretchCopy( newDC.m_hDC, bFlipX ? newSize.cx : 0, bFlipY ? newSize.cy : 0, bFlipX ? -newSize.cx : newSize.cx, bFlipY ? -newSize.cy : newSize.cy, m_dc.m_hDC, 0, 0, m_size.cx, m_size.cy ); } else { StretchCopy( newDC.m_hDC, bFlipX ? newSize.cx : 0, bFlipY ? newSize.cy : 0, m_size.cx, m_size.cy, m_dc.m_hDC, 0, 0, m_size.cx, m_size.cy ); }
COLORREF crOldBk = newDC.SetBkColor( crRight ); CBitmap* pbmOldMask = newMaskDC.SelectObject( &newMaskBitmap );
if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL) { CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
if (pTool->ExpandPolyRegion( newSize.cx, newSize.cy )) { newMaskDC.PatBlt( 0, 0, newSize.cx, newSize.cy, BLACKNESS );
if (m_cRgnPolyFreeHandSel.GetSafeHandle()) newMaskDC.FillRgn( &m_cRgnPolyFreeHandSel, CBrush::FromHandle( (HBRUSH)::GetStockObject( WHITE_BRUSH ) ) ); } } else { newMaskDC.PatBlt( 0, 0, newSize.cx, newSize.cy, WHITENESS ); }
newMaskDC.BitBlt( 0, 0, newSize.cx, newSize.cy, &newDC, 0, 0, DSna ); newDC.SetBkColor( crOldBk );
if (ppalOldSrc) m_dc.SelectPalette( ppalOldSrc, FALSE );
if (ppalOldDest) newDC.SelectPalette( ppalOldDest, FALSE );
if (m_hbmOld) m_dc.SelectObject( CBitmap::FromHandle( m_hbmOld ) );
if (m_hbmMaskOld) m_maskDC.SelectObject( CBitmap::FromHandle( m_hbmMaskOld ) );
m_dc.DeleteDC(); m_maskDC.DeleteDC(); m_bitmap.DeleteObject(); m_maskBitmap.DeleteObject();
m_dc.Attach( newDC.Detach() ); m_bitmap.Attach( newBitmap.Detach() ); m_maskDC.Attach( newMaskDC.Detach() ); m_maskBitmap.Attach( newMaskBitmap.Detach() );
m_hbmOld = (HBITMAP)(pbmOld->GetSafeHandle()); m_hbmMaskOld = (HBITMAP)(pbmOldMask->GetSafeHandle()); }
m_size.cx = newSize.cx; m_size.cy = newSize.cy;
return TRUE; }
#if defined(DEBUGSHOWBITMAPS)
void DebugShowBitmap(HDC hdcSrc, int x, int y, int wid, int hgt) { HDC hdcDst = GetDC(NULL); BitBlt(hdcDst, 0, 0, wid, hgt, hdcSrc, x, y, SRCCOPY); ReleaseDC(NULL, hdcDst); } #endif
BOOL QuickColorToMono(CDC* pdcMono, int xMono, int yMono, int cx, int cy, CDC *pdcColor, int xColor, int yColor, DWORD dwROP, COLORREF crTrans) { RGBQUAD rgb[256]; int nColors = GetDIBColorTable(pdcColor->m_hDC, 0, 256, &rgb[0]); if (nColors == 0) { return(FALSE); }
RGBQUAD rgbWhite; rgbWhite.rgbRed = 255; rgbWhite.rgbGreen = 255; rgbWhite.rgbBlue = 255; rgbWhite.rgbReserved = 0;
RGBQUAD rgbBlack; rgbBlack.rgbRed = 0; rgbBlack.rgbGreen = 0; rgbBlack.rgbBlue = 0; rgbBlack.rgbReserved = 0;
RGBQUAD rgbTemp[256];
switch ((BYTE)((crTrans)>>24)) { case 0: case 2: { RGBQUAD rgbTrans; rgbTrans.rgbRed = GetRValue(crTrans); rgbTrans.rgbGreen = GetGValue(crTrans); rgbTrans.rgbBlue = GetBValue(crTrans); rgbTrans.rgbReserved = 0;
for (int nColor=nColors-1; nColor>=0; --nColor) { if (memcmp(&rgb[nColor], &rgbTrans, sizeof(rgbTrans)) == 0) { rgbTemp[nColor] = rgbWhite; } else { rgbTemp[nColor] = rgbBlack; } }
break; }
// We can put support for different COLORREF formats here
default: return(FALSE); }
SetDIBColorTable(pdcColor->m_hDC, 0, nColors, &rgbTemp[0]); pdcMono->BitBlt(xMono, yMono, cx, cy, pdcColor, xColor, yColor, dwROP); SetDIBColorTable(pdcColor->m_hDC, 0, nColors, &rgb[0]);
return(TRUE); }
#define COLORTOMONOBUG
#ifdef COLORTOMONOBUG
void CImgBrush::ColorToMonoBitBlt(CDC* pdcMono, int xMono, int yMono, int cx, int cy, CDC *pdcColor, int xColor, int yColor, DWORD dwROP, COLORREF transparentColor) { if (QuickColorToMono(pdcMono, xMono, yMono, cx, cy, pdcColor, xColor, yColor, dwROP, transparentColor)) { return; }
CDC dcColor; CTempBitmap bmColor; CBitmap* pbmOldColor = NULL;
// Use a moderate-sized intermediate bitmap
int cyStep = 0xffff / cx; cyStep = max(1, min(cy, cyStep));
HDC hdcScreen = GetDC(NULL); BOOL bError = (!dcColor.CreateCompatibleDC(NULL) || !bmColor.CreateCompatibleBitmap(CDC::FromHandle(hdcScreen), cx, cyStep) || (pbmOldColor = dcColor.SelectObject(&bmColor))==NULL); ReleaseDC(NULL, hdcScreen);
if (bError) { theApp.SetGdiEmergency(FALSE); return; }
CPalette* ppalOld = SetBrushPalette( pdcColor, FALSE ); CPalette* ppalOldColor = SetBrushPalette( &dcColor, FALSE ); dcColor.SetBkColor( transparentColor );
int yStep; for (yStep=0; yStep<cy; yStep+=cyStep) { if (cyStep > cy - yStep) { cyStep = cy - yStep; }
dcColor.BitBlt(0, 0, cx, cyStep, pdcColor, xColor, yColor+yStep, SRCCOPY); pdcMono->BitBlt(xMono, yMono+yStep, cx, cyStep, &dcColor, 0, 0, dwROP);
DebugShowBitmap(pdcMono->m_hDC, xMono, yMono, cx, cy); }
if (ppalOld) { pdcColor->SelectPalette( ppalOld, FALSE ); }
dcColor.SelectObject(pbmOldColor);
if (ppalOldColor) { dcColor.SelectPalette( ppalOldColor, FALSE ); } } #endif // COLORTOMONOBUG
void CImgBrush::RecalcMask( COLORREF transparentColor ) { if (! m_dc.GetSafeHdc() || ! m_maskDC.m_hDC) return;
#ifndef COLORTOMONOBUG
CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE ); COLORREF oldBkColor = m_dc.SetBkColor( transparentColor ); #endif // COLORTOMONOBUG
if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL) { m_maskDC.PatBlt( 0, 0, m_size.cx, m_size.cy, BLACKNESS );
if (m_cRgnPolyFreeHandSel.GetSafeHandle()) m_maskDC.FillRgn( &m_cRgnPolyFreeHandSel, CBrush::FromHandle( (HBRUSH)::GetStockObject( WHITE_BRUSH ) ) );
if (! m_bOpaque) // can't test true, since bitfield
#ifdef COLORTOMONOBUG
ColorToMonoBitBlt(&m_maskDC, 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, DSna, transparentColor); #else // COLORTOMONOBUG
m_maskDC.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, DSna ); #endif // COLORTOMONOBUG
} else { #ifdef COLORTOMONOBUG
ColorToMonoBitBlt(&m_maskDC, 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, NOTSRCCOPY, transparentColor); #else // COLORTOMONOBUG
m_maskDC.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, NOTSRCCOPY ); #endif // COLORTOMONOBUG
}
#ifndef COLORTOMONOBUG
m_dc.SetBkColor( oldBkColor );
if (ppalOld) m_dc.SelectPalette( ppalOld, FALSE ); #endif // COLORTOMONOBUG
}
void GetMonoBltColors(HDC hDC, HBITMAP hBM, COLORREF& crNewBk, COLORREF& crNewText) { crNewBk = RGB(0xff, 0xff, 0xff); crNewText = RGB(0x00, 0x00, 0x00);
RGBQUAD rq; if (GetDIBColorTable(hDC, 0, 1, &rq) == 1) { if (hBM == NULL) { hBM = (HBITMAP) GetCurrentObject(hDC, OBJ_BITMAP); }
WORD nMaxIndex = 0xff;
BITMAP bm; if (GetObject(hBM, sizeof(bm), &bm)) { nMaxIndex = (1 << bm.bmBitsPixel) - 1; }
crNewBk = DIBINDEX(nMaxIndex); crNewText = DIBINDEX(0x00); } }
// This handles drawing the brush with Draw Opaque turned off.
//
void CImgBrush::BltMatte(IMG* pimg, CPoint topLeft) { COLORREF crNewBk, crNewText; GetMonoBltColors(pimg->hDC, pimg->hBitmap, crNewBk, crNewText);
COLORREF crOldBk = SetBkColor(pimg->hDC, crNewBk); COLORREF crOldText = SetTextColor(pimg->hDC, crNewText); CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE ); // Background ??
// Copying from a bitmap...
DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy); BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_dc.m_hDC, 0, 0, DSx); DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_maskDC.m_hDC, 0, 0, DSna); DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_dc.m_hDC, 0, 0, DSx); DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
if (ppalOld) m_dc.SelectPalette( ppalOld, FALSE ); // Background ??
SetBkColor(pimg->hDC, crOldBk); SetTextColor(pimg->hDC, crOldText); }
// This handles drawing the brush with Draw Opaque turned on.
//
void CImgBrush::BltReplace(IMG* pimg, CPoint topLeft) { int iToolID = CImgTool::GetCurrentID();
if (iToolID == IDMB_PICKRGNTOOL) { BltMatte( pimg, topLeft ); } else { CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE ); // Background ??
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_dc.m_hDC, 0, 0, SRCCOPY);
if (ppalOld) m_dc.SelectPalette( ppalOld, FALSE ); // Background ??
} }
// This handles erasing with the brush (draws mask in solid color).
//
void CImgBrush::BltColor(IMG* pimg, CPoint topLeft, COLORREF color) { COLORREF crOldBk = SetBkColor(pimg->hDC, color); COLORREF crOldText = SetTextColor(pimg->hDC, RGB(0, 0, 0));
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_maskDC.m_hDC, 0, 0, DSx);
SetBkColor(pimg->hDC, RGB(255, 255, 255));
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_maskDC.m_hDC, 0, 0, DSna);
SetBkColor(pimg->hDC, color);
BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy, m_maskDC.m_hDC, 0, 0, DSx);
SetTextColor(pimg->hDC, crOldText); SetBkColor(pimg->hDC, crOldBk); }
|