// FingerCellView.cpp : implementation of the CFingerCellView class
//
#include "stdafx.h"
#include "FingerCell.h"
#include "FingerCellDoc.h"
#include "FingerCellView.h"
#include <Winuser.h>
#include <wingdi.h>
#include <Bmp.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFingerCellView

IMPLEMENT_DYNCREATE(CFingerCellView, CScrollView)

BEGIN_MESSAGE_MAP(CFingerCellView, CScrollView)
	//{{AFX_MSG_MAP(CFingerCellView)			
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

#define BLOCK_SIZE 16
#define PI 3.1415926535897932384626433832795

/////////////////////////////////////////////////////////////////////////////
// CFingerCellView construction/destruction

CFingerCellView::CFingerCellView()
{
}

CFingerCellView::~CFingerCellView()
{
}

BOOL CFingerCellView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CFingerCellView drawing

inline int Round(double x)
{
	return (int)(x < 0 ? x - 0.5 : x + 0.5);
}

inline void PaintBO(CDC* dc, int x, int y, BYTE dir, int zoom)
{
	double hbs = BLOCK_SIZE * zoom / 100.0 / 2;
	double a = dir * PI / 180.0;
	int dx = Round(cos(a) * hbs);
	int dy = Round(sin(a) * hbs);
	dc->MoveTo(x, y);
	dc->LineTo(x + dx, y + dy);
	dc->MoveTo(x, y);
	dc->LineTo(x - dx, y - dy);
}

inline void PaintDir(CDC* dc, int x, int y, BYTE dir, int length, int zoom)
{
	length = length * zoom / 100;
	double a = dir * PI / 128.0;
	int dx = Round(cos(a) * length);
	int dy = Round(sin(a) * length);
	dc->MoveTo(x, y);
	dc->LineTo(x + dx, y + dy);
}

inline void DrawFeatures(CDC* pDC, int x, int y, HNFRecord features, CFingerCellDoc* pDoc, int zoom)
{
	COLORREF minutia_color = RGB(255, 0, 0);

	HBRUSH old_brush = (HBRUSH) pDC->SelectObject(GetStockObject(NULL_BRUSH));

	if(pDoc->ShowFeatures())
	{
		HPEN pen = ::CreatePen(PS_SOLID, max(1, Round(zoom / 100.0)), minutia_color);
		HPEN old_pen = (HPEN) pDC->SelectObject(pen);
		int xx, yy, s = max(1, Round(3 * zoom / 100.0));
		NInt minutiaCount;
		NFRecordGetMinutiaCount(features, &minutiaCount);

		for(int i = 0; i < minutiaCount; i++)
		{
			NFMinutia  minutia;
			NFRecordGetMinutia(features, i, &minutia);

			xx = x + minutia.X * zoom / 100;
			yy = y + minutia.Y * zoom / 100;
			pDC->Ellipse(xx - s, yy - s, xx + s + 1, yy + s + 1);
			PaintDir(pDC, xx, yy, minutia.Angle, 10, zoom);
		}
		pDC->SelectObject(old_pen);
		DeleteObject(pen);
	}
	pDC->SelectObject(old_brush);
}

void CFingerCellView::OnDraw(CDC* pDC)
{
	CRect wndRect;
	GetClientRect(&wndRect);

	// Workaround for VIEWSCRL.CPP omission of an erase in the ScrollBy() ScrollWindowEX call.
	pDC->FillSolidRect(wndRect,pDC->GetBkColor());

	CFingerCellDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	HNImage limg = pDoc->GetLeftImage();
	HNImage rimg = pDoc->GetRightImage();

	HNFRecord lfeatures = pDoc->GetLeftFeatures();
	HNFRecord rfeatures = pDoc->GetRightFeatures();
	
	// Workaround for lack of origins in WCE
	// Also, note that SetScrollSizes should use the MM_TEXT map mode
	int nOrgX = -GetScrollPosition().x;
	int nOrgY = -GetScrollPosition().y;

	NUInt width;
	if (limg == NULL)
		return;

	INT zoom = pDoc->GetZoom() * 500/pDoc->GetLeftImageDPI();
	if (pDoc->ShowBinaryImage() == TRUE || lfeatures == NULL)
	{
		Draw(pDC->GetSafeHdc(), nOrgX, nOrgY, lfeatures == NULL, zoom, limg);
	}

	NImageGetWidth(limg, &width);
	width = width*zoom/100+3;

	if (rimg != NULL)
	{
		zoom = pDoc->GetZoom() * 500/pDoc->GetRightImageDPI();
		if (pDoc->ShowBinaryImage() == TRUE || rfeatures == NULL)
			Draw(pDC->GetSafeHdc(), nOrgX+width+3, nOrgY, rfeatures == NULL, zoom, rimg);
	}

	zoom = pDoc->GetZoom();

	if (lfeatures)
		DrawFeatures(pDC, nOrgX, nOrgY, lfeatures, pDoc, zoom);

	if (rfeatures)
		DrawFeatures(pDC, nOrgX+width+3, nOrgY, rfeatures, pDoc, zoom);
}

void CFingerCellView::Draw(HDC dc, int xx, int yy, BOOL GrayScale, int zoom, HNImage hImage)
{
	NUInt width;
	NUInt height;

	NImageGetWidth(hImage, &width);
	NImageGetHeight(hImage, &height);

	NRgb minColor = NRgbConst(0, 234, 0);
	NRgb minColorGray = NRgbConst(0, 0, 0);
	NRgb maxColor = NRgbConst(255, 255, 255);
	HNImage hColorImage;
	NImagesGetGrayscaleColorWrapper(hImage, GrayScale ? minColorGray : minColor, maxColor, &hColorImage);

	HBITMAP hBitmap;
	BmpSaveImageToHBitmap(hColorImage, (NHandle *)&hBitmap);
	NImageFree(hColorImage);
	CBitmap * cb = CBitmap::FromHandle(hBitmap);

	CDC cdc;
	cdc.Attach(dc);

	CDC bdc;
	bdc.CreateCompatibleDC(&cdc);
	bdc.SelectObject(&*cb);

	cdc.StretchBlt(xx, yy, width*zoom/100, height*zoom/100, &bdc, 0, 0, width, height, SRCCOPY);

	bdc.DeleteDC();
	cb->DeleteObject();

	cdc.Detach();
}

void CFingerCellView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();
	CSize sizeTotal;

	sizeTotal.cx = sizeTotal.cy = 100;
	SetScrollSizes(MM_TEXT, sizeTotal);
}

/////////////////////////////////////////////////////////////////////////////
// CFingerCellView diagnostics

#ifdef _DEBUG
void CFingerCellView::AssertValid() const
{
	CScrollView::AssertValid();
}

////void CFingerCellView::Dump(CDumpContext& dc) const
////{
////	CScrollView::Dump(dc);
////}

CFingerCellDoc* CFingerCellView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFingerCellDoc)));
	return (CFingerCellDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFingerCellView message handlers


BOOL CFingerCellView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}


BOOL CFingerCellView::OnEraseBkgnd(CDC* pDC) 
{
	return CScrollView::OnEraseBkgnd(pDC);
}

void CFingerCellView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
	CFingerCellDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	HNImage limg = pDoc->GetLeftImage();
	HNImage rimg = pDoc->GetRightImage();

	if (limg == NULL)
	{
		SetScrollSizes(MM_TEXT, CSize(1,1));
		Invalidate(NULL);
		UpdateWindow();
		return;
	}

	int zoom = pDoc->GetZoom() * 500/pDoc->GetLeftImageDPI();
	NUInt lwidth;
	NUInt lheight;

	NImageGetHeight(limg, &lheight);
	NImageGetWidth(limg, &lwidth);

	lwidth = lwidth*zoom/100;
	lheight = lheight*zoom/100;

	NUInt rwidth = 0;
	NUInt rheight = lheight;

	if (rimg != NULL)
	{
		zoom = pDoc->GetZoom() * 500/pDoc->GetRightImageDPI();
		NImageGetHeight(rimg, &rheight);
		NImageGetWidth(rimg, &rwidth);
		rwidth = rwidth*zoom/100;
		rheight = rheight*zoom/100;
	}

	SetScrollSizes(MM_TEXT, CSize(lwidth+rwidth+3,max(lheight,rheight)));

	Invalidate(NULL);
	UpdateWindow();

	UNREFERENCED_PARAMETER(pSender);
	UNREFERENCED_PARAMETER(lHint);
	UNREFERENCED_PARAMETER(pHint);
}
