Files
MinecraftConsoles/Minecraft.Client/Xbox/Font/XUI_FontRenderer.cpp

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 );
}