308 lines
9.1 KiB
C++
308 lines
9.1 KiB
C++
#include "stdafx.h"
|
|
#include "XUI_FontRenderer.h"
|
|
#include "XUI_Font.h"
|
|
#include "XUI_FontData.h"
|
|
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
|
|
|
extern IDirect3DDevice9 *g_pD3DDevice;
|
|
extern void GetRenderAndSamplerStates(IDirect3DDevice9 *pDevice,DWORD *RenderStateA,DWORD *SamplerStateA);
|
|
extern void SetRenderAndSamplerStates(IDirect3DDevice9 *pDevice,DWORD *RenderStateA,DWORD *SamplerStateA);
|
|
|
|
XUI_FontRenderer::XUI_FontRenderer()
|
|
{
|
|
ZeroMemory(m_loadedFontData, sizeof(XUI_FontData*) * eFontData_MAX);
|
|
|
|
//XuiFontSetRenderer(this);
|
|
|
|
//Minecraft *pMinecraft=Minecraft::GetInstance();
|
|
|
|
//ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys);
|
|
//m_fScreenWidth=(float)pMinecraft->width_phys;
|
|
//m_fRawWidth=(float)ssc.rawWidth;
|
|
//m_fScreenHeight=(float)pMinecraft->height_phys;
|
|
//m_fRawHeight=(float)ssc.rawHeight;
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::Init( float fDpi )
|
|
{
|
|
return( S_OK );
|
|
|
|
}
|
|
|
|
VOID XUI_FontRenderer::Term()
|
|
{
|
|
return;
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::GetCaps( DWORD * pdwCaps )
|
|
{
|
|
if( pdwCaps != NULL )
|
|
{
|
|
// setting this means XUI calls the DrawCharsToDevice method
|
|
*pdwCaps = XUI_FONT_RENDERER_CAP_INTERNAL_GLYPH_CACHE | XUI_FONT_RENDERER_CAP_POINT_SIZE_RESPECTED | XUI_FONT_RENDERER_STYLE_DROPSHADOW;
|
|
}
|
|
return ( S_OK );
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::CreateFont( const TypefaceDescriptor * pTypefaceDescriptor, float fPointSize, DWORD dwStyle, DWORD dwReserved, HFONTOBJ * phFont )
|
|
{
|
|
float fXuiSize = fPointSize * ( 16.0f / 14.0f );
|
|
//float fXuiSize = fPointSize * ( 16.0f / 16.0f );
|
|
fXuiSize /= 4.0f;
|
|
fXuiSize = floor( fXuiSize );
|
|
int xuiSize = (int)(fXuiSize * 4.0f);
|
|
if( xuiSize < 1 ) xuiSize = 8;
|
|
|
|
// 4J Stu - We have fonts based on multiples of 8 or 12
|
|
// We don't want to make the text larger as then it may not fit in the box specified
|
|
// so we decrease the size until we find one that will look ok
|
|
while( xuiSize%8!=0 && xuiSize%12!=0 ) xuiSize -= 2;
|
|
|
|
//app.DebugPrintf("point size is: %f, xuiSize is: %d\n", fPointSize, xuiSize);
|
|
|
|
XUI_Font *font = NULL;
|
|
XUI_FontData *fontData = NULL;
|
|
FLOAT scale = 1;
|
|
|
|
eFontData efontdata;
|
|
if( xuiSize%12==0 )
|
|
{
|
|
scale = xuiSize/12;
|
|
efontdata = eFontData_Mojangles_11;
|
|
}
|
|
else
|
|
{
|
|
scale = xuiSize/8;
|
|
efontdata = eFontData_Mojangles_7;
|
|
}
|
|
|
|
font = m_loadedFonts[efontdata][scale];
|
|
if (font == NULL)
|
|
{
|
|
fontData = m_loadedFontData[efontdata];
|
|
if (fontData == NULL)
|
|
{
|
|
SFontData *sfontdata;
|
|
switch (efontdata)
|
|
{
|
|
case eFontData_Mojangles_7: sfontdata = &SFontData::Mojangles_7; break;
|
|
case eFontData_Mojangles_11: sfontdata = &SFontData::Mojangles_11; break;
|
|
default: sfontdata = NULL; break;
|
|
}
|
|
|
|
fontData = new XUI_FontData();
|
|
fontData->Create(*sfontdata);
|
|
|
|
m_loadedFontData[efontdata] = fontData;
|
|
}
|
|
|
|
font = new XUI_Font( efontdata, scale, fontData );
|
|
m_loadedFonts[efontdata][scale] = font;
|
|
}
|
|
font->IncRefCount();
|
|
|
|
*phFont = (HFONTOBJ)font;
|
|
return S_OK;
|
|
}
|
|
|
|
VOID XUI_FontRenderer::ReleaseFont( HFONTOBJ hFont )
|
|
{
|
|
XUI_Font *xuiFont = (XUI_Font*) hFont;
|
|
if (xuiFont != NULL)
|
|
{
|
|
xuiFont->DecRefCount();
|
|
if (xuiFont->refCount <= 0)
|
|
{
|
|
auto it = m_loadedFonts[xuiFont->m_iFontData].find(xuiFont->m_fScaleFactor);
|
|
if (it != m_loadedFonts[xuiFont->m_iFontData].end()) m_loadedFonts[xuiFont->m_iFontData].erase(it);
|
|
delete hFont;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::GetFontMetrics( HFONTOBJ hFont, XUIFontMetrics *pFontMetrics )
|
|
{
|
|
if( hFont == 0 || pFontMetrics == 0 ) return E_INVALIDARG;
|
|
|
|
XUI_Font *font = (XUI_Font *)hFont;
|
|
|
|
pFontMetrics->fLineHeight = (font->m_fontData->getFontYAdvance() + 1) * font->m_fYScaleFactor;
|
|
pFontMetrics->fMaxAscent = font->m_fontData->getMaxAscent() * font->m_fYScaleFactor;
|
|
pFontMetrics->fMaxDescent = font->m_fontData->getMaxDescent() * font->m_fYScaleFactor;
|
|
pFontMetrics->fMaxHeight = font->m_fontData->getFontHeight() * font->m_fYScaleFactor;
|
|
pFontMetrics->fMaxWidth = font->m_fontData->getFontMaxWidth() * font->m_fXScaleFactor;
|
|
pFontMetrics->fMaxAdvance = font->m_fontData->getFontMaxWidth() * font->m_fXScaleFactor;
|
|
|
|
//*pFontMetrics = font->m_fontMetrics; // g_fontMetrics;
|
|
return( S_OK );
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::GetCharMetrics( HFONTOBJ hFont, WCHAR wch, XUICharMetrics *pCharMetrics )
|
|
{
|
|
if (hFont == 0 || pCharMetrics == 0) return E_INVALIDARG;
|
|
|
|
XUI_Font *font = (XUI_Font *)hFont;
|
|
XUI_FontData::SChar sChar = font->m_fontData->getChar(wch);
|
|
|
|
pCharMetrics->fMinX = sChar.getMinX() * font->m_fYScaleFactor;
|
|
pCharMetrics->fMinY = sChar.getMinY() * font->m_fYScaleFactor;
|
|
pCharMetrics->fMaxX = sChar.getMaxX() * font->m_fYScaleFactor;
|
|
pCharMetrics->fMaxY = sChar.getMaxY() * font->m_fYScaleFactor;
|
|
pCharMetrics->fAdvance = sChar.getAdvance() * font->m_fYScaleFactor;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::DrawCharToTexture( HFONTOBJ hFont, WCHAR wch, HXUIDC hDC, IXuiTexture * pTexture, UINT x, UINT y, UINT width, UINT height, UINT insetX, UINT insetY )
|
|
{
|
|
if( hFont==0 || pTexture==NULL ) return E_INVALIDARG;
|
|
return( S_OK );
|
|
}
|
|
|
|
HRESULT XUI_FontRenderer::DrawCharsToDevice( HFONTOBJ hFont, CharData * pCharData, DWORD dwCount, RECT *pClipRect, HXUIDC hDC, D3DXMATRIX * pWorldViewProj )
|
|
{
|
|
if( hFont == 0 ) return E_INVALIDARG;
|
|
if( dwCount == 0 ) return( S_OK );
|
|
|
|
DWORD RenderStateA[8];
|
|
DWORD SamplerStateA[5];
|
|
XMVECTOR vconsts[20];
|
|
XMVECTOR pconsts[20];
|
|
XUI_Font *font = (XUI_Font *)hFont;
|
|
|
|
// 4J-PB - if we're in 480 Widescreen mode, we need to ensure that the font characters are aligned on an even boundary if they are a 2x multiple
|
|
if(!RenderManager.IsHiDef())
|
|
{
|
|
if(RenderManager.IsWidescreen())
|
|
{
|
|
float fScaleX, fScaleY;
|
|
font->GetScaleFactors(&fScaleX,&fScaleY);
|
|
int iScaleX=fScaleX;
|
|
int iScaleY=fScaleY;
|
|
|
|
if(iScaleX%2==0)
|
|
{
|
|
int iWorldX=pWorldViewProj->_41;
|
|
pWorldViewProj->_41 = (float)(iWorldX & -2);
|
|
}
|
|
if(iScaleY%2==0)
|
|
{
|
|
int iWorldY=pWorldViewProj->_42;
|
|
pWorldViewProj->_42 = (float)(iWorldY & -2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// make x an even number for 480 4:3
|
|
int iWorldX=pWorldViewProj->_41;
|
|
pWorldViewProj->_41 = (float)(iWorldX & -2);
|
|
|
|
// 480 SD mode - y needs to be on a pixel boundary when multiplied by 1.5, so if it's an odd number, subtract 1/3 from it
|
|
int iWorldY=pWorldViewProj->_42;
|
|
if(iWorldY%2==1)
|
|
{
|
|
pWorldViewProj->_42-=1.0f/3.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_pD3DDevice->GetVertexShaderConstantF( 0, (float *)vconsts, 20 );
|
|
g_pD3DDevice->GetPixelShaderConstantF( 0, (float *)pconsts, 20 );
|
|
g_pD3DDevice->SetRenderState(D3DRS_HALFPIXELOFFSET, TRUE);
|
|
GetRenderAndSamplerStates(g_pD3DDevice, RenderStateA, SamplerStateA );
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
RenderManager.Set_matrixDirty();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glOrtho(0, 1280.0f, 720.0f, 0, 1000, 3000);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
glTranslatef(0, 0, -2000);
|
|
glColor4f(1.0f,1.0f,1.0f,1.0f);
|
|
float matrixCopy[16];
|
|
memcpy(matrixCopy, pWorldViewProj, 64);
|
|
matrixCopy[11] = 0.0f;
|
|
matrixCopy[12] = floor(matrixCopy[12] + 0.5f);
|
|
matrixCopy[13] = floor(matrixCopy[13] + 0.5f);
|
|
matrixCopy[14] = floor(matrixCopy[14] + 0.5f);
|
|
matrixCopy[15] = 1.0f;
|
|
glMultMatrixf(matrixCopy);
|
|
|
|
|
|
float lineXPos = 0.0f;
|
|
float lineYPos = 0.0f;
|
|
DWORD colour = 0;
|
|
DWORD style = 0;
|
|
#if 1
|
|
for( int i = 0; i < dwCount; i++ )
|
|
{
|
|
wstring string;
|
|
string.push_back(pCharData[i].wch);
|
|
lineYPos = pCharData[i].y;
|
|
lineXPos = pCharData[i].x;
|
|
colour = pCharData[i].dwColor;
|
|
style = pCharData[i].dwStyle;
|
|
|
|
//if(pCharData[i].wch > font->m_fontData->getMaxGlyph())
|
|
if ( !font->m_fontData->getChar(pCharData[i].wch).hasChar() )
|
|
{
|
|
// Can't render this character, fallback to the default renderer
|
|
app.OverrideFontRenderer(false,false);
|
|
break;
|
|
}
|
|
#else
|
|
DWORD i = 0;
|
|
while( i < dwCount )
|
|
{
|
|
wstring string;
|
|
lineYPos = pCharData[i].y;
|
|
lineXPos = pCharData[i].x;
|
|
colour = pCharData[i].dwColor;
|
|
style = pCharData[i].dwStyle;
|
|
|
|
while(i < dwCount && pCharData[i].y == lineYPos)
|
|
{
|
|
string.push_back(pCharData[i].wch);
|
|
++i;
|
|
}
|
|
#endif
|
|
|
|
bool dropShadow = false;
|
|
if( (style & XUI_FONT_STYLE_DROPSHADOW) == XUI_FONT_STYLE_DROPSHADOW) dropShadow = true;
|
|
|
|
//int yPos = (int)pCharData[i].y + (int)(font->m_fontMetrics.fLineHeight - font->m_fontMetrics.fMaxAscent)/2;
|
|
//if( (pCharData[i].dwStyle & XUI_FONT_STYLE_VERTICAL_CENTER) == XUI_FONT_STYLE_VERTICAL_CENTER)
|
|
//{
|
|
// yPos = (pClipRect->bottom - (int)font->m_fontMetrics.fLineHeight) / 2;
|
|
//}
|
|
|
|
if(dropShadow)
|
|
{
|
|
DWORD shadowColour;
|
|
XuiGetTextDropShadowColor(hDC, &shadowColour);
|
|
// 4J Stu - Shadow colour is currently ignored
|
|
font->DrawShadowText( lineXPos,lineYPos,colour,shadowColour,string.c_str() );
|
|
//drawShadow(thisChar, (int)pCharData[i].x, yPos, pCharData[i].dwColor );
|
|
}
|
|
else
|
|
{
|
|
font->DrawText( lineXPos,lineYPos,colour,string.c_str() );
|
|
//draw(thisChar, (int)pCharData[i].x, yPos, pCharData[i].dwColor, false );
|
|
}
|
|
}
|
|
|
|
g_pD3DDevice->SetVertexShaderConstantF( 0, (float *)vconsts, 20 );
|
|
g_pD3DDevice->SetPixelShaderConstantF( 0, (float *)pconsts, 20 );
|
|
SetRenderAndSamplerStates(g_pD3DDevice, RenderStateA, SamplerStateA );
|
|
g_pD3DDevice->SetRenderState(D3DRS_HALFPIXELOFFSET, FALSE);
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
XuiRenderRestoreState(hDC);
|
|
|
|
return( S_OK );
|
|
}
|