|
|
/****************************************************************************
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(); }
/***************************************************************************/
|