/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//////////////////////////////////////////////////////////////////////////////////////
// @@ @@@ @@@ @@ @@@@@ //
// @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ //
// @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ //
// @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ //
// @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ //
// @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ //
// @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ //
// @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ //
// @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ //
// @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ //
// @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ //
//@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ //
//@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ //
//@@@ @@@ @@@ @@@@@ @@ @@@ //
// @@@ @@@ @@ @@ STUDIOS //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// ARX_Text
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Text Management
//
// Updates: (date) (person) (update)
//
// Copyright (c) 1999-2000 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
#include
#include "ARX_Loc.h"
#include "ARX_Text.h"
#include "danae.h"
#include "EERIEDraw.h"
#include "HermesMain.h"
#define _CRTDBG_MAP_ALLOC
#include
#include
//-----------------------------------------------------------------------------
_TCHAR * lpszFontMenu = NULL;
_TCHAR * lpszFontIngame = NULL;
_TCHAR tUText[8192];
CARXTextManager * pTextManage = NULL;
CARXTextManager * pTextManageFlyingOver = NULL;
HMODULE hUnicodeLibrary = NULL;
//-----------------------------------------------------------------------------
HFONT InBookFont = NULL;
HFONT hFontRedist = NULL;
HFONT hFontMainMenu = NULL;
HFONT hFontMenu = NULL;
HFONT hFontControls = NULL;
HFONT hFontCredits = NULL;
HFONT hFontInGame = NULL;
HFONT hFontInGameNote = NULL;
extern long CHINESE_VERSION;
extern long EAST_EUROPE;
//-----------------------------------------------------------------------------
void FontError()
// XS : Lil' wrapper around FormatMessage & GetLastError
{
#ifdef _DEBUG
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
MessageBox(NULL, (LPCSTR)lpMsgBuf, (LPCSTR)"Font Error", MB_OK | MB_ICONINFORMATION);
#endif
}
//-----------------------------------------------------------------------------
long ARX_UNICODE_ForceFormattingInRect(HFONT _hFont, _TCHAR * _lpszUText, int _iSpacingY, RECT _rRect)
{
int iTemp = 0;
if (danaeApp.m_pddsRenderTarget)
{
HDC hDC;
if (SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
int iLenght = _tcslen(_lpszUText);
int iHeight = 0;
SIZE sSize;
int iOldTemp;
bool bWrite;
sSize.cx = sSize.cy = 0 ;
SelectObject(hDC, _hFont);
while (1)
{
bWrite = true;
int iLenghtCurr = _rRect.left;
iOldTemp = iTemp;
ARX_CHECK(iTemp < iLenght);
for (; iTemp < iLenght ; iTemp++)
{
GetTextExtentPoint32W(hDC,
&_lpszUText[iTemp],
1,
&sSize);
{
if ((_lpszUText[iTemp] == _T('\n')) ||
(_lpszUText[iTemp] == _T('*')))
{
iHeight += _iSpacingY + sSize.cy;
bWrite = false;
_rRect.top += _iSpacingY + sSize.cy;
iTemp++;
break;
}
}
iLenghtCurr += sSize.cx;
if (iLenghtCurr > _rRect.right)
{
iHeight += _iSpacingY + sSize.cy;
if (CHINESE_VERSION)
{
iTemp--;
}
else
{
while ((_lpszUText[iTemp] != _T(' ')) && (iTemp > 0)) iTemp--;
}
bWrite = false;
_rRect.top += _iSpacingY + sSize.cy;
iTemp++;
break;
}
}
if ((iTemp == iLenght) ||
((_rRect.top + sSize.cy) > _rRect.bottom))
{
break;
}
}
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
}
}
return iTemp;
}
//-----------------------------------------------------------------------------
long ARX_UNICODE_FormattingInRect(HDC _hDC, _TCHAR * _lpszUText, int _iSpacingY, RECT & _rRect)
{
int iLenght = _tcslen(_lpszUText);
int iHeight = 0;
SIZE sSize;
int iOldTemp;
bool bWrite;
sSize.cx = sSize.cy = 0;
int iTemp = 0;
typedef bool (APIENTRY * TextOutW)(HDC hdc, // handle to DC
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
_TCHAR * lpString, // character string
int cbString // number of characters
);
TextOutW Unicows_TextOutW = (TextOutW)GetProcAddress(hUnicodeLibrary, "TextOutW");
while (1)
{
bWrite = true;
int iLenghtCurr = _rRect.left;
iOldTemp = iTemp;
for (; iTemp < iLenght; iTemp++)
{
GetTextExtentPoint32W(_hDC,
&_lpszUText[iTemp],
1,
&sSize);
if ((_lpszUText[iTemp] == _T('\n')) ||
(_lpszUText[iTemp] == _T('*')))
{
iHeight += _iSpacingY + sSize.cy;
_lpszUText[iTemp] = _T('\0');
bWrite = false;
Unicows_TextOutW(_hDC, _rRect.left, _rRect.top, &_lpszUText[iOldTemp], _tcslen(&_lpszUText[iOldTemp]));
_rRect.top += _iSpacingY + sSize.cy;
iTemp++;
break;
}
iLenghtCurr += sSize.cx;
if (iLenghtCurr > _rRect.right)
{
iHeight += _iSpacingY + sSize.cy;
if (CHINESE_VERSION)
{
_TCHAR * ptexttemp = (_TCHAR *)malloc((iTemp - iOldTemp + 1) << 1);
_tcsncpy(ptexttemp, &_lpszUText[iOldTemp], iTemp - iOldTemp);
ptexttemp[iTemp-iOldTemp] = _T('\0');
Unicows_TextOutW(_hDC, _rRect.left, _rRect.top, ptexttemp, _tcslen(ptexttemp));
free((void *)ptexttemp);
ptexttemp = NULL;
iTemp--;
}
else
{
while ((_lpszUText[iTemp] != _T(' ')) && (iTemp > 0)) iTemp--;
_lpszUText[iTemp] = _T('\0');
Unicows_TextOutW(_hDC, _rRect.left, _rRect.top, &_lpszUText[iOldTemp], _tcslen(&_lpszUText[iOldTemp]));
}
bWrite = false;
_rRect.top += _iSpacingY + sSize.cy;
iTemp++;
break;
}
}
if (iTemp == iLenght) break;
if (iTemp == iOldTemp) break;
}
if (bWrite)
{
iHeight += _iSpacingY + sSize.cy;
if (!Unicows_TextOutW(_hDC, _rRect.left, _rRect.top, &_lpszUText[iOldTemp], _tcslen(&_lpszUText[iOldTemp])))
{
FontError();
}
_rRect.top += _iSpacingY + sSize.cy;
}
return iHeight;
}
//-----------------------------------------------------------------------------
long ARX_UNICODE_DrawTextInRect(float x, float y,
float maxx, float maxy,
_TCHAR * _lpszUText,
COLORREF col,
COLORREF bcol,
HFONT font,
HRGN hRgn,
HDC hHDC
)
{
HDC hDC = NULL;
// Get a DC for the surface. Then, write out the buffer
if (danaeApp.m_pddsRenderTarget)
{
if (hHDC)
{
hDC = hHDC;
}
if (hHDC || SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
_tcscpy(tUText, _lpszUText);
if (hRgn)
{
SelectClipRgn(hDC,
hRgn);
}
if (bcol == 0x00FF00FF) SetBkMode(hDC, TRANSPARENT);
else
{
SetBkMode(hDC, OPAQUE);
SetBkColor(hDC, bcol);
}
SetTextColor(hDC, col);
SelectObject(hDC, font);
RECT rect;
rect.top = (long)y;
rect.left = (long)x;
rect.right = (long)maxx;
long n = ARX_UNICODE_FormattingInRect(hDC, tUText, 0, rect);
rect.top = (long)y;
rect.bottom = ((long)y) + n;
SelectClipRgn(hDC,
NULL);
if (!hHDC)
{
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
}
return n;
}
}
return 0;
}
//-----------------------------------------------------------------------------
long ARX_TEXT_Draw(LPDIRECT3DDEVICE7 pd3dDevice,
HFONT ef,
float x, float y,
long spacingx, long spacingy,
_TCHAR * car,
COLORREF colo, COLORREF bcol)
{
if (car == NULL) return 0;
if (car[0] == 0) return 0;
//ArxFont
ARX_UNICODE_DrawTextInRect(x, y, 9999.f, 999.f, car, colo, bcol, ef);
return 15 + spacingy;
}
long ARX_TEXT_DrawRect(LPDIRECT3DDEVICE7 pd3dDevice,
HFONT ef,
float x, float y,
long spacingx, long spacingy,
float maxx, float maxy,
_TCHAR * car,
COLORREF colo,
HRGN _hRgn,
COLORREF bcol,
long flags)
{
bcol = RGB((bcol >> 16) & 255, (bcol >> 8) & 255, (bcol) & 255);
colo = RGB((colo >> 16) & 255, (colo >> 8) & 255, (colo) & 255);
return ARX_UNICODE_DrawTextInRect(x, y, maxx, maxy, car, colo, bcol, ef, _hRgn);
}
//-----------------------------------------------------------------------------
float DrawBookTextInRect(float x, float y, float maxx, float maxy, _TCHAR * text, COLORREF col, COLORREF col2, HFONT font)
{
return (float)ARX_TEXT_DrawRect(GDevice, font,
(BOOKDECX + x) * Xratio, (BOOKDECY + y) * Yratio, -3, 0,
(BOOKDECX + maxx) * Xratio, (BOOKDECY + maxy) * Yratio, text, col, NULL, col2);
}
//-----------------------------------------------------------------------------
void DrawBookTextCenter(float x, float y, _TCHAR * text, COLORREF col, COLORREF col2, HFONT font)
{
UNICODE_ARXDrawTextCenter((BOOKDECX + x)*Xratio, (BOOKDECY + y)*Yratio, text, col, col2, font);
}
//-----------------------------------------------------------------------------
long UNICODE_ARXDrawTextCenter(float x, float y, _TCHAR * str, COLORREF col, COLORREF bcol, HFONT font)
{
HDC hDC;
// Get a DC for the surface. Then, write out the buffer
if (danaeApp.m_pddsRenderTarget)
{
if (SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
if (bcol == 0x00FF00FF) SetBkMode(hDC, TRANSPARENT);
else
{
SetBkMode(hDC, OPAQUE);
SetBkColor(hDC, bcol);
}
SetTextColor(hDC, col);
SelectObject(hDC, font);
SIZE siz;
GetTextExtentPoint32W(hDC, // handle to DC
str, // character string
_tcslen(str), // number of characters
&siz // size
);
RECT rect;
rect.top = (long)y;
rect.bottom = (long)999;
rect.left = (long)x - (siz.cx >> 1);
rect.right = (long)999;
TextOutW(hDC, rect.left, rect.top, str, _tcslen(str));
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
return siz.cx;
}
}
return 0;
}
long UNICODE_ARXDrawTextCenteredScroll(float x, float y, float x2, _TCHAR * str, COLORREF col, COLORREF bcol, HFONT font, int iTimeScroll, float fSpeed, int iNbLigne, int iTimeOut)
{
RECT rRect;
ARX_CHECK_LONG(y);
ARX_CHECK_LONG(x + x2); //IF OK, x - x2 cannot overflow
rRect.left = ARX_CLEAN_WARN_CAST_LONG(x - x2);
rRect.top = ARX_CLEAN_WARN_CAST_LONG(y);
rRect.right = ARX_CLEAN_WARN_CAST_LONG(x + x2);
if (pTextManage)
{
pTextManage->AddText(font,
str,
rRect,
col,
bcol,
iTimeOut,
iTimeScroll,
fSpeed,
iNbLigne
);
return ARX_CLEAN_WARN_CAST_LONG(x2);
}
return 0;
}
//-----------------------------------------------------------------------------
void ARX_Allocate_Text(_TCHAR *&dest, _TCHAR * id_string)
{
if (dest != NULL)
{
free(dest);
dest = NULL;
}
_TCHAR output[4096];
PAK_UNICODE_GetPrivateProfileString(id_string, _T("string"), _T("default"), output, 4096, NULL);
dest = (_TCHAR *)malloc((_tcslen(output) + 1) * sizeof(_TCHAR));
_tcscpy(dest, output);
}
//-----------------------------------------------------------------------------
struct _FONT_HEADER
{
ULONG ulVersion;
USHORT usNumTables;
USHORT usSearchRange;
USHORT usEntrySelector;
USHORT usRangeShift;
};
//-----------------------------------------------------------------------------
struct _FONT_TABLE_HEADER
{
ULONG ulTag;
ULONG ulCheckSum;
ULONG ulOffset;
ULONG ulLength;
};
//-----------------------------------------------------------------------------
struct _FONT_NAMING_HEADER
{
USHORT usFormat;
USHORT usNbNameRecords;
USHORT usOffsetStorage; //(from start of table)
};
//-----------------------------------------------------------------------------
struct _FONT_NAMING_NAMERECORD
{
USHORT usPlatformID;
USHORT usPlatformSpecificEncodingID;
USHORT usLanguageID;
USHORT usNameID;
USHORT usStringLength;
USHORT usStringOffset; //from start of storage area (in bytes)
};
//-----------------------------------------------------------------------------
ULONG LilEndianLong(ULONG ulValue)
{
return (
MAKELONG(
MAKEWORD(HIBYTE(HIWORD(ulValue)), LOBYTE(HIWORD(ulValue))),
MAKEWORD(HIBYTE(LOWORD(ulValue)), LOBYTE(LOWORD(ulValue)))
)
);
}
//-----------------------------------------------------------------------------
USHORT LilEndianShort(USHORT ulValue)
{
return (
MAKEWORD(HIBYTE(ulValue), LOBYTE(ulValue))//,
);
}
//-----------------------------------------------------------------------------
_TCHAR * GetFontName(char * _lpszFileName)
{
DWORD dwSize;
DWORD dwRead;
int iResult;
HANDLE hFile = CreateFile(_lpszFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "FontName :: File not Found", _lpszFileName, MB_OK);
return NULL;
}
dwSize = GetFileSize(hFile, NULL);
// HEADER
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
_FONT_HEADER FH;
iResult = ReadFile(hFile, &FH, sizeof(FH), &dwRead, NULL);
if (iResult == 0)
{
MessageBox(NULL, "FontName :: Pas lu!", "", MB_OK);
}
// TABLE HEADERS
for (int i = 0; i < FH.usNumTables; i++)
{
_FONT_TABLE_HEADER FTH;
iResult = ReadFile(hFile, &FTH, sizeof(FTH), &dwRead, NULL);
if (iResult == 0)
{
MessageBox(NULL, "FontName :: Pas lu!", "", MB_OK);
}
char szName[5];
szName[0] = LOBYTE(LOWORD(FTH.ulTag));
szName[1] = HIBYTE(LOWORD(FTH.ulTag));
szName[2] = LOBYTE(HIWORD(FTH.ulTag));
szName[3] = HIBYTE(HIWORD(FTH.ulTag));
szName[4] = 0;
if (strcmp(szName, "name") == 0)
{
FTH.ulOffset = LilEndianLong(FTH.ulOffset);
SetFilePointer(hFile, FTH.ulOffset, NULL, FILE_BEGIN);
_FONT_NAMING_HEADER FNH;
iResult = ReadFile(hFile, &FNH, sizeof(FNH), &dwRead, NULL);
if (iResult == 0)
{
MessageBox(NULL, "FontName :: Pas lu!", "", MB_OK);
}
FNH.usNbNameRecords = LilEndianShort(FNH.usNbNameRecords);
FNH.usOffsetStorage = LilEndianShort(FNH.usOffsetStorage);
for (int j = 0; j < FNH.usNbNameRecords; j++)
{
_FONT_NAMING_NAMERECORD FNN;
iResult = ReadFile(hFile, &FNN, sizeof(FNN), &dwRead, NULL);
if (iResult == 0)
{
MessageBox(NULL, "FontName :: Pas lu!", "", MB_OK);
}
FNN.usNameID = LilEndianShort(FNN.usNameID);
FNN.usPlatformID = LilEndianShort(FNN.usPlatformID);
FNN.usStringLength = LilEndianShort(FNN.usStringLength);
FNN.usStringOffset = LilEndianShort(FNN.usStringOffset);
FNN.usLanguageID = LilEndianShort(FNN.usLanguageID);
if (FNN.usLanguageID == 1033)
if (FNN.usNameID == 1)
{
SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
SetFilePointer(hFile, FTH.ulOffset + FNH.usOffsetStorage + FNN.usStringOffset, NULL, FILE_BEGIN);
wchar_t szName[256];
ZeroMemory(szName, 256);
assert(FNN.usStringLength < 256);
iResult = ReadFile(hFile, szName, FNN.usStringLength, &dwRead, NULL);
if (iResult == 0)
{
MessageBox(NULL, "FontName :: Pas lu!", "", MB_OK);
}
for (int k = 0; k<(FNN.usStringLength >> 1); k++)
{
szName[k] = LilEndianShort(szName[k]);
}
_TCHAR * szText = new _TCHAR[(FNN.usStringLength>>1)+1]; //@HACK
_tcscpy(szText, szName);
CloseHandle(hFile);
return szText;
}
}
}
}
CloseHandle(hFile);
return NULL;
}
void _ShowText(char * text)
{
if (GDevice)
{
GDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0L);
if (danaeApp.DANAEStartRender())
{
HDC hDC;
if (danaeApp.m_pddsRenderTarget)
{
if (SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
SetTextColor(hDC, RGB(0, 255, 0));
SetBkMode(hDC, TRANSPARENT);
ExtTextOut(hDC, 0, 0, 0, NULL, text, lstrlen(text), NULL);
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
}
}
danaeApp.DANAEEndRender();
danaeApp.m_pFramework->ShowFrame();
}
}
}
//-----------------------------------------------------------------------------
void ARX_Text_Init(ARX_TEXT * _pArxText)
{
_pArxText->eType = ARX_TEXT_ONCE;
_pArxText->hFont = hFontInGame;
_pArxText->rRect.top = 0;
_pArxText->rRect.left = 0;
_pArxText->rRect.right = 0;
_pArxText->rRect.bottom = 0;
_pArxText->rRectClipp.top = 0;
_pArxText->rRectClipp.bottom = 0;
_pArxText->rRectClipp.left = 0;
_pArxText->rRectClipp.right = 0;
_pArxText->lpszUText = NULL;
_pArxText->fDeltaY = 0;
_pArxText->fSpeedScrollY = 0;
_pArxText->lCol = RGB(1, 1, 1);
_pArxText->lBkgCol = 0x00FF00FF;
_pArxText->lTimeScroll = 0;
_pArxText->lTimeOut = 0;
_pArxText->lTailleLigne = 0;
_pArxText->iNbLineClip = 0;
}
//-----------------------------------------------------------------------------
CARXTextManager::CARXTextManager()
{
vText.clear();
}
//-----------------------------------------------------------------------------
CARXTextManager::~CARXTextManager()
{
vector::iterator itManage;
for (itManage = vText.begin(); itManage < vText.end(); itManage++)
{
if (*itManage)
{
if ((*itManage)->lpszUText)
{
delete[](*itManage)->lpszUText;
(*itManage)->lpszUText = NULL;
}
free((void *)(*itManage));
*itManage = NULL;
}
}
vText.clear();
}
//-----------------------------------------------------------------------------
bool CARXTextManager::AddText(HFONT _hFont, _TCHAR * _lpszUText, RECT & _rRect, long _lCol, long _lBkgCol, long _lTimeOut, long _lTimeScroll, float _fSpeedScroll, int iNbLigneClipp)
{
if ((_lpszUText) && (_hFont))
{
ARX_TEXT * pArxText = (ARX_TEXT *) malloc(sizeof(ARX_TEXT));
if (pArxText)
{
pArxText->lpszUText = new _TCHAR[_tcsclen(_lpszUText)+1];
if (pArxText->lpszUText)
{
pArxText->hFont = _hFont;
_tcscpy(pArxText->lpszUText, _lpszUText);
pArxText->eType = ARX_TEXT_STAY;
pArxText->rRect = _rRect;
pArxText->lCol = _lCol;
pArxText->lBkgCol = _lBkgCol;
pArxText->lTimeScroll = _lTimeScroll;
pArxText->fDeltaY = 0.f;
pArxText->fSpeedScrollY = _fSpeedScroll;
pArxText->lTimeOut = _lTimeOut;
if (iNbLigneClipp)
{
HDC hDC;
SIZE sSize;
if (SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
SelectObject(hDC, pArxText->hFont);
GetTextExtentPoint32W(hDC,
pArxText->lpszUText,
_tcslen(pArxText->lpszUText),
&sSize);
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
pArxText->lTailleLigne = sSize.cy;
sSize.cy *= iNbLigneClipp;
}
else
{
sSize.cy = _rRect.bottom - _rRect.top;
pArxText->lTailleLigne = sSize.cy;
}
SetRect(&pArxText->rRectClipp,
pArxText->rRect.left,
pArxText->rRect.top,
pArxText->rRect.right,
pArxText->rRect.top + sSize.cy);
}
else
{
pArxText->rRectClipp = pArxText->rRect;
}
vText.insert(vText.end(), pArxText);
return true;
}
free((void *)pArxText);
pArxText = NULL;
}
}
return false;
}
//-----------------------------------------------------------------------------
bool CARXTextManager::AddText(ARX_TEXT * _pArxText)
{
if ((_pArxText) && (_pArxText->lpszUText) && (_pArxText->hFont))
{
ARX_TEXT * pArxText = (ARX_TEXT *) malloc(sizeof(ARX_TEXT));
if (pArxText)
{
pArxText->lpszUText = new _TCHAR[_tcsclen(_pArxText->lpszUText)+1];
if (pArxText->lpszUText)
{
pArxText->hFont = _pArxText->hFont;
_tcscpy(pArxText->lpszUText, _pArxText->lpszUText);
pArxText->eType = _pArxText->eType;
pArxText->rRect = _pArxText->rRect;
pArxText->lCol = _pArxText->lCol;
pArxText->lBkgCol = _pArxText->lBkgCol;
pArxText->lTimeScroll = _pArxText->lTimeScroll;
pArxText->fDeltaY = _pArxText->fDeltaY;
pArxText->fSpeedScrollY = _pArxText->fSpeedScrollY;
pArxText->lTimeOut = _pArxText->lTimeOut;
pArxText->iNbLineClip = _pArxText->iNbLineClip;
if (pArxText->iNbLineClip)
{
HDC hDC;
SIZE sSize;
if (SUCCEEDED(danaeApp.m_pddsRenderTarget->GetDC(&hDC)))
{
SelectObject(hDC, pArxText->hFont);
GetTextExtentPoint32W(hDC,
pArxText->lpszUText,
_tcslen(pArxText->lpszUText),
&sSize);
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
pArxText->lTailleLigne = sSize.cy;
sSize.cy *= pArxText->iNbLineClip;
}
else
{
sSize.cy = pArxText->rRect.bottom - pArxText->rRect.top;
pArxText->lTailleLigne = sSize.cy;
}
SetRect(&pArxText->rRectClipp,
pArxText->rRect.left,
pArxText->rRect.top,
pArxText->rRect.right,
pArxText->rRect.top + sSize.cy);
}
else
{
pArxText->rRectClipp = pArxText->rRect;
}
vText.insert(vText.end(), pArxText);
return true;
}
free((void *)pArxText);
pArxText = NULL;
}
}
return false;
}
//-----------------------------------------------------------------------------
void CARXTextManager::Update(float _fDiffFrame)
{
vector::iterator itManage;
ARX_CHECK_INT(_fDiffFrame);
int _iDiffFrame = ARX_CLEAN_WARN_CAST_INT(_fDiffFrame);
for (itManage = vText.begin(); itManage < vText.end();)
{
ARX_TEXT * pArxText = *itManage;
if (pArxText)
{
if ((pArxText->lTimeOut < 0))
{
delete[] pArxText->lpszUText;
pArxText->lpszUText = NULL;
free((void *)pArxText);
pArxText = NULL;
itManage = vText.erase(itManage);
continue;
}
pArxText->lTimeOut -= _iDiffFrame;
if ((pArxText->lTimeScroll < 0) &&
(pArxText->fDeltaY < (pArxText->rRect.bottom - pArxText->rRectClipp.bottom))
)
{
pArxText->fDeltaY += pArxText->fSpeedScrollY * (float)_iDiffFrame;
if (pArxText->fDeltaY >= (pArxText->rRect.bottom - pArxText->rRectClipp.bottom))
{
pArxText->fDeltaY = ARX_CLEAN_WARN_CAST_FLOAT(pArxText->rRect.bottom - pArxText->rRectClipp.bottom);
}
}
else
{
pArxText->lTimeScroll -= _iDiffFrame;
}
}
itManage++;
}
}
//-----------------------------------------------------------------------------
void CARXTextManager::Render()
{
vector::iterator itManage;
itManage = vText.begin();
HDC hDC = NULL;
if (danaeApp.m_pddsRenderTarget && vText.size())
{
danaeApp.m_pddsRenderTarget->GetDC(&hDC);
}
while (itManage != vText.end())
{
ARX_TEXT * pArxText = *itManage;
if (pArxText)
{
HRGN hRgn = NULL;
hRgn = CreateRectRgn(pArxText->rRectClipp.left,
pArxText->rRectClipp.top,
pArxText->rRectClipp.right,
pArxText->rRectClipp.bottom);
pArxText->rRect.bottom = pArxText->rRect.top + ARX_UNICODE_DrawTextInRect(ARX_CLEAN_WARN_CAST_FLOAT(pArxText->rRect.left),
pArxText->rRect.top - pArxText->fDeltaY,
ARX_CLEAN_WARN_CAST_FLOAT(pArxText->rRect.right),
0,
pArxText->lpszUText,
pArxText->lCol,
pArxText->lBkgCol,
pArxText->hFont,
hRgn,
hDC);
if (hRgn)
{
DeleteObject(hRgn);
}
if (pArxText->eType == ARX_TEXT_ONCE)
{
delete[] pArxText->lpszUText;
pArxText->lpszUText = NULL;
free((void *)pArxText);
pArxText = NULL;
itManage = vText.erase(itManage);
continue;
}
}
itManage++;
}
if (hDC)
{
danaeApp.m_pddsRenderTarget->ReleaseDC(hDC);
}
}
//-----------------------------------------------------------------------------
void CARXTextManager::Clear()
{
vector::iterator itManage;
for (itManage = vText.begin(); itManage < vText.end(); itManage++)
{
if (*itManage)
{
if ((*itManage)->lpszUText)
{
delete[](*itManage)->lpszUText;
(*itManage)->lpszUText = NULL;
}
free((void *)(*itManage));
*itManage = NULL;
}
}
vText.clear();
}
int Traffic(int iFontSize)
{
iFontSize = (int)(float)(iFontSize * Yratio);
if (CHINESE_VERSION)
{
if (iFontSize < 14)
iFontSize = 12;
else if (iFontSize < 15)
iFontSize = 14;
else if (iFontSize < 18)
iFontSize = 15;
else if (iFontSize <= 29)
iFontSize = 18;
else
iFontSize = 30;
}
return iFontSize;
}
HFONT _CreateFont(
int nHeight, // height of font
int nWidth, // average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute option
DWORD fdwUnderline, // underline attribute option
DWORD fdwStrikeOut, // strikeout attribute option
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
_TCHAR * lpszFace // typeface name
)
{
typedef HFONT(APIENTRY * CreateFontW)(
int nHeight, // height of font
int nWidth, // average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute option
DWORD fdwUnderline, // underline attribute option
DWORD fdwStrikeOut, // strikeout attribute option
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPWSTR wlpszFace // typeface name
);
if (!hUnicodeLibrary)
{
return NULL;
}
CreateFontW Unicows_CreateFontW = (CreateFontW)GetProcAddress(hUnicodeLibrary, "CreateFontW");
/*
ANSI_CHARSET
BALTIC_CHARSET
CHINESEBIG5_CHARSET
DEFAULT_CHARSET
EASTEUROPE_CHARSET
GB2312_CHARSET
GREEK_CHARSET
HANGUL_CHARSET
MAC_CHARSET
OEM_CHARSET
RUSSIAN_CHARSET
SHIFTJIS_CHARSET
SYMBOL_CHARSET
TURKISH_CHARSET
VIETNAMESE_CHARSET
*/
if (EAST_EUROPE)
{
fdwCharSet = CHINESEBIG5_CHARSET;
}
//HFONT ret = CreateFont(
HFONT ret = Unicows_CreateFontW(
nHeight, // height of font
nWidth, // average character width
nEscapement, // angle of escapement
nOrientation, // base-line orientation angle
fnWeight, // font weight
fdwItalic, // italic attribute option
fdwUnderline, // underline attribute option
fdwStrikeOut, // strikeout attribute option
fdwCharSet, // character set identifier
fdwOutputPrecision, // output precision
fdwClipPrecision, // clipping precision
fdwQuality, // output quality
fdwPitchAndFamily, // pitch and family
(LPWSTR)lpszFace // typeface name
);
if (!ret)
{
FontError();
}
return ret;
}
//-----------------------------------------------------------------------------
void ARX_Text_Init()
{
ARX_Text_Close();
hUnicodeLibrary = LoadLibraryA("unicows.dll");
if (!hUnicodeLibrary)
{
exit(0);
}
ARX_Localisation_Init();
_TCHAR wtx[256];
char tx[256];
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx.ttf"); // Full path
if (!FileExist(tx))
{
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx_default.ttf"); // Full path
}
MultiByteToWideChar(CP_ACP, 0, tx , -1, wtx, 256); // XS : We need to pass a unicode string to AddFontResourceW
typedef int (APIENTRY * AddFontRessourceW)(const wchar_t *);
AddFontRessourceW Unicows_AddFontResourceW = (AddFontRessourceW)GetProcAddress(hUnicodeLibrary, "AddFontResourceW");
lpszFontIngame = GetFontName(tx);
if (Unicows_AddFontResourceW(wtx) == 0)
{
FontError();
}
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx.ttf");
if (!FileExist(tx))
{
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx_default.ttf"); // Full path
}
MultiByteToWideChar(CP_ACP, 0, tx , -1, wtx, 256); // XS : We need to pass an unicode string to AddFontResourceW
lpszFontMenu = GetFontName(tx);
if (Unicows_AddFontResourceW(wtx) == 0)
{
FontError();
}
pTextManage = new CARXTextManager();
pTextManageFlyingOver = new CARXTextManager();
if (!hFontMainMenu)
{
int iFontSize = 48;//58;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_mainmenu_size"), _T("string"), _T("58"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
if (!hFontMainMenu)
{
hFontMainMenu = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontMenu);
}
}
if (!hFontMenu)
{
int iFontSize = 32;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_menu_size"), _T("string"), _T("32"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
if (!hFontMenu)
{
hFontMenu = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontMenu);
}
}
if (!hFontControls)
{
int iFontSize = 16;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_menucontrols_size"), _T("string"), _T("22"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
if (!hFontControls)
{
hFontControls = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontMenu);
}
}
if (!hFontCredits)
{
int iFontSize = 32;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_menucredits_size"), _T("string"), _T("36"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
if (!hFontCredits)
{
hFontCredits = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontMenu);
}
}
if (!hFontRedist)
{
int iFontSize = 16;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_redist_size"), _T("string"), _T("18"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
hFontRedist = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontIngame);
}
// NEW QUEST
if (Yratio > 1.f)
{
Yratio *= .8f;
}
if (!hFontInGame)
{
int iFontSize = 16;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_book_size"), _T("string"), _T("18"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
if (!hFontInGame)
{
hFontInGame = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontIngame);
}
}
if (!hFontInGameNote)
{
int iFontSize = 16;//18;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_note_size"), _T("string"), _T("18"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
hFontInGameNote = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontIngame);
}
if (!InBookFont)
{
int iFontSize = 16;
_TCHAR szUT[256];
PAK_UNICODE_GetPrivateProfileString(_T("system_font_book_size"), _T("string"), _T("18"), szUT, 256, NULL);
iFontSize = _ttoi(szUT);
iFontSize = Traffic(iFontSize);
InBookFont = _CreateFont(
iFontSize,
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
VARIABLE_PITCH,
lpszFontIngame);
}
}
//-----------------------------------------------------------------------------
void ARX_Text_Close()
{
if (!hUnicodeLibrary)
{
hUnicodeLibrary = LoadLibraryA("unicows.dll");
}
if (lpszFontIngame)
{
delete [] lpszFontIngame;
lpszFontIngame = NULL;
}
if (lpszFontMenu)
{
delete [] lpszFontMenu;
lpszFontMenu = NULL;
}
typedef ATOM(APIENTRY * RemoveRessourceW)(const wchar_t *);
RemoveRessourceW Unicows_RemoveRessourceW = (RemoveRessourceW)GetProcAddress(hUnicodeLibrary, "RemoveFontResourceW");
_TCHAR wtx[256];
char tx[256];
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx.ttf"); // Full path
if (!FileExist(tx))
{
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx_default.ttf"); // Full path
}
MultiByteToWideChar(CP_ACP, 0, tx , -1, wtx, 256); // XS : We need to pass a unicode string to RemoveRessourceW
lpszFontIngame = GetFontName(tx);
if (Unicows_RemoveRessourceW(wtx) == 0)
{
// FontError(); // XS : Annoying popup, uncomment if you really want to track something down.
}
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx.ttf"); // Full path
if (!FileExist(tx))
{
sprintf(tx, "%smisc\\%s", Project.workingdir, "arx_default.ttf"); // Full path
}
MultiByteToWideChar(CP_ACP, 0, tx , -1, wtx, 256); // XS : We need to pass a unicode string to RemoveRessourceW
lpszFontMenu = GetFontName(tx);
if (Unicows_RemoveRessourceW(wtx) == 0)
{
// FontError();// XS : Annoying popup, uncomment if you really want to track something down.
}
ARX_Localisation_Close();
if (pTextManage)
{
delete pTextManage;
pTextManage = NULL;
}
if (pTextManageFlyingOver)
{
delete pTextManageFlyingOver;
pTextManageFlyingOver = NULL;
}
if (InBookFont)
{
DeleteObject(InBookFont);
InBookFont = NULL;
}
if (hFontRedist)
{
DeleteObject(hFontRedist);
hFontRedist = NULL;
}
if (hFontMainMenu)
{
DeleteObject(hFontMainMenu);
hFontMainMenu = NULL;
}
if (hFontMenu)
{
DeleteObject(hFontMenu);
hFontMenu = NULL;
}
if (hFontControls)
{
DeleteObject(hFontControls);
hFontControls = NULL;
}
if (hFontCredits)
{
DeleteObject(hFontCredits);
hFontCredits = NULL;
}
if (hFontInGame)
{
DeleteObject(hFontInGame);
hFontInGame = NULL;
}
if (hFontInGameNote)
{
DeleteObject(hFontInGameNote);
hFontInGameNote = NULL;
}
FreeLibrary(hUnicodeLibrary);
hUnicodeLibrary = NULL;
}