You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
5.4 KiB
C++

2 years ago
// XTPChartDeviceContext.cpp
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPIntel80Helpers.h"
#include "GraphicLibrary/GdiPlus/GdiPlus.h"
#include "../Types/XTPChartTypes.h"
#include "XTPChartDeviceContext.h"
#include "XTPChartDeviceCommand.h"
#pragma comment(lib, "GdiPlus.lib")
#pragma comment(lib, "GLU32.lib")
using namespace Gdiplus;
using namespace Gdiplus::DllExports;
#pragma warning(disable:4510)
#pragma warning(disable:4610)
//////////////////////////////////////////////////////////////////////////
// CXTPChartDeviceContext
class CXTPChartDeviceContext::CGdiPlus
{
public:
CGdiPlus()
{
m_hModule = NULL;
m_nGdiplusToken = NULL;
m_nCount = 0;
}
public:
void Register(BOOL bInit);
public:
HMODULE m_hModule;
ULONG_PTR m_nGdiplusToken;
int m_nCount;
};
CXTPChartDeviceContext::CGdiPlus* CXTPChartDeviceContext::GetGdiPlus()
{
static CGdiPlus GdiPlus;
return &GdiPlus;
}
void CXTPChartDeviceContext::CGdiPlus::Register(BOOL bInit)
{
if (bInit)
{
m_nCount++;
if (m_nCount > 1)
return;
ASSERT(m_nGdiplusToken == 0 && m_hModule == 0);
m_hModule = LoadLibrary(_T("GdiPlus.dll"));
if (m_hModule)
{
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_nGdiplusToken, &gdiplusStartupInput, NULL);
}
}
else
{
m_nCount--;
if (m_nCount != 0)
return;
if (m_hModule)
{
GdiplusShutdown(m_nGdiplusToken);
FreeLibrary(m_hModule);
}
m_hModule = NULL;
m_nGdiplusToken = 0;
}
}
void CXTPChartDeviceContext::Register(BOOL bInit)
{
GetGdiPlus()->Register(bInit);
}
CXTPChartDeviceContext::CXTPChartDeviceContext(CXTPChartContainer* pContainer, HDC hDC)
{
m_pContainer = pContainer;
m_hDC = hDC;
GdipCreateFromHDC(hDC, &m_pGpGraphics);
// Get screen DPI
HDC hScreenDC = ::GetDC(NULL);
int nLogPixelsX = ::GetDeviceCaps(hScreenDC, LOGPIXELSX);
int nLogPixelsY = ::GetDeviceCaps(hScreenDC, LOGPIXELSY);
VERIFY(1 == ::ReleaseDC(NULL, hScreenDC));
// Get output DPI
REAL dpix;
REAL dpiy;
GdipGetDpiX(m_pGpGraphics, &dpix);
GdipGetDpiY(m_pGpGraphics, &dpiy);
GdipScaleWorldTransform(m_pGpGraphics, dpix/nLogPixelsX, dpiy/nLogPixelsY, MatrixOrderAppend);
GdipSetPageUnit(m_pGpGraphics, UnitPixel);
GdipSetSmoothingMode(m_pGpGraphics, SmoothingModeHighSpeed);
}
CXTPChartDeviceContext::CXTPChartDeviceContext(CXTPChartContainer* pContainer, Graphics* pGraphics, HDC hDC)
{
USES_PROTECTED_ACCESS(CXTPChartDeviceContext, Graphics, GpGraphics, nativeGraphics);
m_pContainer = pContainer;
m_hDC = hDC;
m_pGpGraphics = PROTECTED_ACCESS(Graphics, pGraphics, nativeGraphics);
GdipSetPageUnit(m_pGpGraphics, UnitPixel);
GdipSetSmoothingMode(m_pGpGraphics, SmoothingModeHighSpeed);
}
CXTPChartDeviceContext::CXTPChartDeviceContext(CXTPChartContainer* pContainer)
{
m_pContainer = pContainer;
m_hDC = NULL;
m_pGpGraphics = NULL;
}
CXTPChartDeviceContext::~CXTPChartDeviceContext()
{
if (m_pGpGraphics)
{
GdipDeleteGraphics(m_pGpGraphics);
}
}
void CXTPChartDeviceContext::Execute(CXTPChartDeviceCommand* pCommand)
{
pCommand->Execute(this);
}
CXTPChartSizeF CXTPChartDeviceContext::MeasureString(const CXTPChartString* pText, CXTPChartFont* pFont)
{
GpFont* pGpFont = NULL;
GdipCreateFontFromLogfont(m_hDC, &pFont->m_lf, &pGpFont);
RectF boundingBox;
RectF layoutRect(0, 0, 0.0f, 0.0f);
GdipMeasureString(m_pGpGraphics, XTP_CT2CW(*pText), -1, pGpFont, &layoutRect, 0, &boundingBox, 0, 0);
CXTPChartSizeF sz;
boundingBox.GetSize((SizeF*)&sz);
GdipDeleteFont(pGpFont);
return sz;
}
BOOL GetEncoderClsid(const WCHAR *pFormat, CLSID *pClsid)
{
UINT num, size;
GdipGetImageEncodersSize(&num, &size);
ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
GdipGetImageEncoders(num, size, pImageCodecInfo);
BOOL found = FALSE;
for (UINT ix = 0; !found && ix < num; ++ix)
{
if (_wcsicmp(pImageCodecInfo[ix].MimeType, pFormat) == 0)
{
*pClsid = pImageCodecInfo[ix].Clsid;
found = TRUE;
break;
}
}
free(pImageCodecInfo);
return found;
}
LPCWSTR GetMimeType(LPCTSTR lpszFileName)
{
int len = (int)_tcslen(lpszFileName);
if (len > 3 && _tcsicmp(lpszFileName + len - 4, _T(".png")) == 0)
return L"image/png";
if (len > 3 && _tcsicmp(lpszFileName + len - 4, _T(".jpg")) == 0)
return L"image/jpeg";
if (len > 3 && _tcsicmp(lpszFileName + len - 4, _T(".gif")) == 0)
return L"image/gif";
return L"image/bmp";
}
void CXTPChartDeviceContext::SaveToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
{
GpBitmap* pGpBitmap = NULL;
GdipCreateBitmapFromHBITMAP(hBitmap, 0, &pGpBitmap);
if (pGpBitmap)
{
CLSID encoder;
if (GetEncoderClsid(GetMimeType(lpszFileName), &encoder))
{
GdipSaveImageToFile(pGpBitmap, XTP_CT2CW(lpszFileName), &encoder, NULL);
}
GdipDisposeImage(pGpBitmap);
}
return;
}