262 lines
8.1 KiB
C++
262 lines
8.1 KiB
C++
|
/****************************************************************************
|
||
|
SKEW.c
|
||
|
|
||
|
The SKEW module handles rotating a rectangular object.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "global.h"
|
||
|
#include "pbrush.h"
|
||
|
#include "pbrusdoc.h"
|
||
|
#include "imgwnd.h"
|
||
|
#include "imgbrush.h"
|
||
|
#include "imgsuprt.h"
|
||
|
#include "bmobject.h"
|
||
|
#include "undo.h"
|
||
|
#include "props.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "memtrace.h"
|
||
|
|
||
|
static int miAngle;
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|
||
|
static int CalcOffset( int iValue )
|
||
|
{
|
||
|
// tan[angle] is the 100000/tangent of angles 1 to 89deg.
|
||
|
static int invtan[90] = { -1, 5728996, 2863625, 1908114, 1430067,
|
||
|
1143005, 951436, 814436, 711537, 631375,
|
||
|
567128, 514455, 470463, 433148, 401078,
|
||
|
373205, 348741, 327085, 307768, 290421,
|
||
|
274748, 260509, 247509, 235585, 224604,
|
||
|
214451, 205030, 196261, 188073, 180405,
|
||
|
173205, 166428, 160034, 153987, 148256,
|
||
|
142815, 137638, 132705, 127994, 123490,
|
||
|
119175, 115037, 111061, 107237, 103553,
|
||
|
100000, 96569, 93252, 90040, 86929,
|
||
|
83910, 80978, 78129, 75355, 72654,
|
||
|
70021, 67451, 64941, 62487, 60086,
|
||
|
57735, 55431, 53171, 50953, 48773,
|
||
|
46631, 44523, 42448, 40403, 38386,
|
||
|
36397, 34433, 32492, 30573, 28675,
|
||
|
26795, 24933, 23087, 21256, 19438,
|
||
|
17633, 15838, 14054, 12279, 10510,
|
||
|
8749, 6993, 5241, 3492, 1746 };
|
||
|
return (((iValue * 1000000 / invtan[miAngle]) + 5) / 10);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|
||
|
void CImgWnd::CmdSkewBrush( int iAngle, BOOL bHorz )
|
||
|
{
|
||
|
BOOL bFullImage = FALSE;
|
||
|
CDC* pdcImg = CDC::FromHandle( m_pImg->hDC );
|
||
|
CDC* pdcSrc = &theImgBrush.m_dc;
|
||
|
CRect rectSlct( 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy );
|
||
|
|
||
|
if (theImgBrush.m_pImg == NULL && ! g_bCustomBrush)
|
||
|
{
|
||
|
bFullImage = TRUE;
|
||
|
pdcSrc = pdcImg;
|
||
|
rectSlct.SetRect( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight );
|
||
|
}
|
||
|
|
||
|
CRect rectSkew = rectSlct;
|
||
|
|
||
|
if (!iAngle || rectSlct.IsRectEmpty() || abs(iAngle) > 89 || abs(iAngle) < 1 )
|
||
|
return;
|
||
|
|
||
|
if (! bFullImage)
|
||
|
{
|
||
|
PrepareForBrushChange( TRUE, TRUE );
|
||
|
HideBrush();
|
||
|
}
|
||
|
// angle is the angle of skew 0 to 90 degrees
|
||
|
// axis is the direction to skew TRUE: horizontal
|
||
|
// the y axis moves by angle
|
||
|
// FALSE: verticle
|
||
|
// the x axis moves by angle
|
||
|
int iWidthSlct = rectSlct.Width();
|
||
|
int iHeightSlct = rectSlct.Height();
|
||
|
|
||
|
miAngle = abs(iAngle);
|
||
|
|
||
|
if (bHorz) // horizontal - create a new bitmap of size = x + y * tan (angle)
|
||
|
rectSkew.right += CalcOffset( iHeightSlct );
|
||
|
else // verticale - create a new bitmap of size = y + x * tan (angle)
|
||
|
rectSkew.bottom += CalcOffset( iWidthSlct );
|
||
|
|
||
|
int iWidthSkew = rectSkew.Width();
|
||
|
int iHeightSkew = rectSkew.Height();
|
||
|
|
||
|
// angle is the angle of skew 0 to 90 degrees
|
||
|
// axis is the direction to skew TRUE: horizontal
|
||
|
// the y axis moves by angle
|
||
|
// FALSE: verticle
|
||
|
// the x axis moves by angle
|
||
|
CDC dcWork;
|
||
|
CBitmap bmWork;
|
||
|
CBrush brBackground;
|
||
|
|
||
|
if (! dcWork.CreateCompatibleDC( pdcImg )
|
||
|
|| ! bmWork.CreateCompatibleBitmap( pdcImg, iWidthSkew, iHeightSkew )
|
||
|
|| ! brBackground.CreateSolidBrush( crRight ))
|
||
|
{
|
||
|
theApp.SetGdiEmergency( TRUE );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CBitmap* pbmOld = dcWork.SelectObject( &bmWork );
|
||
|
CPalette* ppalOld = SetImgPalette( &dcWork, FALSE );
|
||
|
|
||
|
dcWork.FillRect( rectSkew, &brBackground );
|
||
|
|
||
|
CPalette* ppalOldSrc = SetImgPalette( pdcSrc, FALSE );
|
||
|
|
||
|
// Skew the bitmap
|
||
|
int mx = 1;
|
||
|
int my = 1; // local variables for the skew
|
||
|
int x = rectSlct.left;
|
||
|
int y = rectSlct.top;
|
||
|
|
||
|
BeginWaitCursor();
|
||
|
|
||
|
if (bHorz) // horizontal
|
||
|
{
|
||
|
if (iAngle > 0)
|
||
|
{
|
||
|
mx = x + CalcOffset( iHeightSlct - y );
|
||
|
// Start at Bottom
|
||
|
for (y = rectSlct.bottom; y >= rectSlct.top; )
|
||
|
{
|
||
|
dcWork.BitBlt( mx, y, iWidthSlct, 1, pdcSrc, x, y, SRCCOPY );
|
||
|
mx = x + CalcOffset( iHeightSlct - y-- );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
x = rectSkew.right - iWidthSlct;
|
||
|
mx = x - CalcOffset( iHeightSlct - y );
|
||
|
for (y = rectSlct.bottom; y >= rectSlct.top; )
|
||
|
{
|
||
|
dcWork.BitBlt( mx, y, iWidthSlct, 1, pdcSrc, rectSlct.left, y, SRCCOPY );
|
||
|
mx = x - CalcOffset( iHeightSlct - y-- );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ // vertical
|
||
|
if (iAngle > 0)
|
||
|
{
|
||
|
my = y + CalcOffset( iWidthSlct - x );
|
||
|
// Start at left
|
||
|
for (x = rectSlct.left - 1; x <= rectSlct.right; )
|
||
|
{
|
||
|
dcWork.BitBlt( x, my, 1, iHeightSlct, pdcSrc, x, y, SRCCOPY );
|
||
|
my = y + CalcOffset( iWidthSlct - x++ );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
y = rectSkew.bottom - iHeightSlct;
|
||
|
my = y - CalcOffset( iWidthSlct - x );
|
||
|
for (x = rectSlct.left - 1; x <= rectSlct.right; )
|
||
|
{
|
||
|
dcWork.BitBlt( x, my, 1, iHeightSlct, pdcSrc, x, rectSlct.top, SRCCOPY );
|
||
|
my = y - CalcOffset( iWidthSlct - x++ );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ppalOldSrc)
|
||
|
pdcSrc->SelectPalette( ppalOldSrc, FALSE );
|
||
|
|
||
|
if (bFullImage)
|
||
|
{
|
||
|
theUndo.BeginUndo( TEXT("Skew Bitmap") );
|
||
|
|
||
|
m_pImg->m_pBitmapObj->SetSizeProp( P_Size, CSize( iWidthSkew, iHeightSkew ) );
|
||
|
|
||
|
m_pImg->cxWidth = iWidthSkew;
|
||
|
m_pImg->cyHeight = iHeightSkew;
|
||
|
|
||
|
SetUndo( m_pImg );
|
||
|
|
||
|
pdcImg->BitBlt( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight, &dcWork, 0, 0, SRCCOPY );
|
||
|
|
||
|
InvalImgRect ( m_pImg, &rectSkew );
|
||
|
CommitImgRect( m_pImg, &rectSkew );
|
||
|
|
||
|
FinishUndo( rectSkew );
|
||
|
|
||
|
theUndo.EndUndo();
|
||
|
|
||
|
DirtyImg( m_pImg );
|
||
|
|
||
|
InvalidateRect( NULL );
|
||
|
UpdateWindow();
|
||
|
|
||
|
dcWork.SelectObject( pbmOld );
|
||
|
bmWork.DeleteObject();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CBitmap bmMask;
|
||
|
|
||
|
if (! bmMask.CreateBitmap( iWidthSkew, iHeightSkew, 1, 1, NULL ))
|
||
|
{
|
||
|
if (ppalOld)
|
||
|
dcWork.SelectPalette( ppalOld, FALSE );
|
||
|
|
||
|
theApp.SetMemoryEmergency( TRUE );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dcWork.SelectObject( pbmOld );
|
||
|
|
||
|
theImgBrush.m_dc.SelectObject( &bmWork );
|
||
|
theImgBrush.m_bitmap.DeleteObject();
|
||
|
theImgBrush.m_bitmap.Attach( bmWork.Detach() );
|
||
|
|
||
|
theImgBrush.m_size.cx = iWidthSkew;
|
||
|
theImgBrush.m_size.cy = iHeightSkew;
|
||
|
|
||
|
VERIFY( theImgBrush.m_maskDC.SelectObject( &bmMask ) ==
|
||
|
&theImgBrush.m_maskBitmap );
|
||
|
|
||
|
theImgBrush.m_maskBitmap.DeleteObject();
|
||
|
theImgBrush.m_maskBitmap.Attach( bmMask.Detach() );
|
||
|
theImgBrush.RecalcMask( crRight );
|
||
|
|
||
|
rectSkew = theImgBrush.m_rcSelection;
|
||
|
|
||
|
mx = 0;
|
||
|
my = 0;
|
||
|
|
||
|
if (bHorz)
|
||
|
mx = CalcOffset( iHeightSlct ) / 2;
|
||
|
else
|
||
|
my = CalcOffset( iWidthSlct ) / 2;
|
||
|
|
||
|
rectSkew.InflateRect( mx, my );
|
||
|
|
||
|
MoveBrush( rectSkew );
|
||
|
}
|
||
|
|
||
|
if (ppalOld)
|
||
|
dcWork.SelectPalette( ppalOld, FALSE );
|
||
|
|
||
|
dcWork.DeleteDC();
|
||
|
|
||
|
EndWaitCursor();
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|