windows-nt/Source/XPSP1/NT/shell/osshell/accesory/mspaint/skew.cpp

262 lines
8.1 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************
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();
}
/***************************************************************************/