/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
|   TextureManager.cpp
|
+ -------------------------------------------------------------------------------------------------
|
+ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include "Common.h"

#include "DataLoad.h"

#include "textureManager.h"

//! コンストラクタ
TextureManager::TextureManager()
{
	m_pCardMask = NULL;
	m_cardSize = 0;
}
//! デストラクタ
TextureManager::~TextureManager()
{
	release();
}

//! 解放
void TextureManager::release(void)
{
	HeapFree(GetProcessHeap(), 0, m_pCardMask);
	for(iteTexture ite = m_textureList.begin(); ite != m_textureList.end(); ite++){
		SAFE_DELETE(*ite);
	}
}

//! カードマスク読み込み
void TextureManager::loadCardMask(void)
{
	// 生成済
	if(m_pCardMask){
		return;
	}

	HANDLE hFile;
	DWORD fSize, br;
	void *orgdata = NULL, *dstdata = NULL;
	UINT32 width, height, pitch, outsize;

	hFile = CreateFile("Image/etc/cardMask.png", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE){
		return;
	}

	fSize = GetFileSize(hFile, NULL);
	orgdata = HeapAlloc(GetProcessHeap(), 0, fSize);

	ReadFile(hFile, orgdata, fSize, &br, NULL);
	CloseHandle(hFile);

	pngparser(&dstdata, orgdata, &width, &height, fSize, &outsize, &pitch);
	HeapFree(GetProcessHeap(), 0, orgdata); orgdata = NULL;

	m_cardSize = outsize;
	m_pCardMask = HeapAlloc(GetProcessHeap(), 0, outsize * 4);
	
	unsigned char *src = (unsigned char *)dstdata;
	unsigned int *dst = (unsigned int *)m_pCardMask;
	for(unsigned int i = 0; i < outsize; i++){
		*dst = ((unsigned int)*src) << 24;
		src++;
		dst++;
	}

	HeapFree(GetProcessHeap(), 0, dstdata);
}


//! カードテクスチャ読み込み
int TextureManager::loadCardTexture(char* pStr)
{
	int ret = -1;

	// 既に読み込んでいる
	for(iteTexture ite = m_textureList.begin(); ite != m_textureList.end(); ite++){
		if(strcmp(pStr, (*ite)->name.c_str()) == 0){
			return(distance(m_textureList.begin(), ite));
		}
	}

	loadCardMask();

	HANDLE hFile;
	HRESULT hr;
	DWORD fSize, br;
	void *orgdata = NULL, *dstdata = NULL;
	UINT32 width, height, pitch, outsize;

	// ファイル取得
	hFile = CreateFile(pStr, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE){
		return(ret);
	}

	// ファイル読み込み
	fSize = GetFileSize(hFile, NULL);

	orgdata = HeapAlloc(GetProcessHeap(), 0, fSize);
	ret = ReadFile(hFile, orgdata, fSize, &br, NULL);
	CloseHandle(hFile);

	// jpg処理
	ret = jpegparser(&dstdata, orgdata, &width, &height, fSize, &outsize, &pitch);
	HeapFree(GetProcessHeap(), 0, orgdata); orgdata = NULL;

	// マスクの適応
	unsigned int *src = (unsigned int *)m_pCardMask;
	unsigned int *dst = (unsigned int *)dstdata;

	for(int i = 0; i < m_cardSize; i++){
		*dst = (*dst & 0x00ffffff) | *src;
		src++;
		dst++;
	}

	m_textureList.push_back(new TEXTURE_DATA());
	TEXTURE_DATA*	pTex = m_textureList.back();

	// テクスチャ生成
	hr = GetDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTex->pTexture, NULL);
	if(FAILED(hr)){
		SAFE_DELETE(m_textureList.back());
		m_textureList.pop_back();
		HeapFree(GetProcessHeap(), 0, dstdata);
		return(ret);
	}
	hr = GetDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex->pShadow, NULL);
	if(FAILED(hr)){
		SAFE_DELETE(m_textureList.back());
		m_textureList.pop_back();
		HeapFree(GetProcessHeap(), 0, dstdata);
		return(ret);
	}

	// テクスチャ合成
	D3DLOCKED_RECT lockRect;
	hr = pTex->pShadow->LockRect(0, &lockRect, NULL, D3DLOCK_DISCARD);
	for(uint i = 0; i < height; i++){
		memcpy((void *)((size_t)lockRect.pBits + i * lockRect.Pitch), (void *)((size_t)dstdata + i * pitch), pitch);
	}
	hr = pTex->pShadow->UnlockRect(0);

	GetDevice()->UpdateTexture(pTex->pShadow, pTex->pTexture);

	HeapFree(GetProcessHeap(), 0, dstdata);

	pTex->name = pStr;
	pTex->width = (int)width;
	pTex->height = (int)height;
	pTex->xPart = 1;
	pTex->yPart = 1;
	pTex->isRev = false;

	ret = distance(m_textureList.begin(), m_textureList.end()-1);

	return(ret);
}

//! テクスチャ読み込み
int TextureManager::loadTexture(char* pStr, int xPart, int yPart, bool isRev)
{
	int ret = -1;

	if(!pStr){
		return(ret);
	}

	// 既に読み込んでいる
	for(iteTexture ite = m_textureList.begin(); ite != m_textureList.end(); ite++){
		if(strcmp(pStr, (*ite)->name.c_str()) == 0 && isRev == (*ite)->isRev){
			return(distance(m_textureList.begin(), ite));
		}
	}

	HANDLE hFile;
	HRESULT hr;
	DWORD fSize, br;
	void *orgdata = NULL, *dstdata = NULL;
	UINT32 width, height, pitch, outsize;
	unsigned char *hdr;

	// ファイル取得
	hFile = CreateFile(pStr, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE){
		return(ret);
	}

	// ファイル読み込み
	fSize = GetFileSize(hFile, NULL);

	orgdata = HeapAlloc(GetProcessHeap(), 0, fSize);
	ret = ReadFile(hFile, orgdata, fSize, &br, NULL);
	CloseHandle(hFile);

	hdr = (unsigned char *)orgdata;

	// jpg処理
	if(hdr[0] == 0xff && hdr[1] == 0xd8)
		ret = jpegparser(&dstdata, orgdata, &width, &height, fSize, &outsize, &pitch);
	// png処理
	if(hdr[0] == 0x89 && hdr[1] == 'P' && hdr[2] == 'N'&& hdr[3] == 'G')
		ret = pngparser(&dstdata, orgdata, &width, &height, fSize, &outsize, &pitch);

	HeapFree(GetProcessHeap(), 0, orgdata); orgdata = NULL;

	// 左右反転
	if(isRev){
		unsigned int *dst = (unsigned int *)dstdata;
		for(uint i = 0; i < width * height; i++){
			uint x = i % width;
//			uint y = i / width;
			if(x < width / 2){
				REPLACE(uint, *dst, *(dst + width - 1 - x*2));
			}
			dst++;
		}

	}

	m_textureList.push_back(new TEXTURE_DATA());
	TEXTURE_DATA*	pTex = m_textureList.back();
	// テクスチャ生成
	hr = GetDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTex->pTexture, NULL);
	if(FAILED(hr)){
		SAFE_DELETE(m_textureList.back());
		m_textureList.pop_back();
		HeapFree(GetProcessHeap(), 0, dstdata);
		return(ret);
	}

	hr = GetDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex->pShadow, NULL);
	if(FAILED(hr)){
		SAFE_DELETE(m_textureList.back());
		m_textureList.pop_back();
		HeapFree(GetProcessHeap(), 0, dstdata);
		return(ret);
	}

	// テクスチャ合成
	D3DLOCKED_RECT lockRect;
	hr = pTex->pShadow->LockRect(0, &lockRect, NULL, D3DLOCK_DISCARD);
	for(uint i = 0; i < height; i++){
		memcpy((void *)((size_t)lockRect.pBits + i * lockRect.Pitch), (void *)((size_t)dstdata + i * pitch), pitch);
	}
	hr = pTex->pShadow->UnlockRect(0);

	GetDevice()->UpdateTexture(pTex->pShadow, pTex->pTexture);

	HeapFree(GetProcessHeap(), 0, dstdata);

	pTex->name = pStr;
	pTex->width = (int)width;
	pTex->height = (int)height;
	pTex->xPart = xPart;
	pTex->yPart = yPart;
	pTex->isRev = isRev;

	ret = distance(m_textureList.begin(), m_textureList.end()-1);

	return(ret);
}

