Blame |
Last modification |
View Log
| RSS feed
#include "SysFont.h"
#include "DDImage.h"
#include "SexyAppBase.h"
#include "Graphics.h"
#include "ImageFont.h"
#include "MemoryImage.h"
#include "D3DInterface.h"
#include "WidgetManager.h"
#include <stdlib.h>
using namespace Sexy;
SysFont::SysFont(const std::string& theFace, int thePointSize, bool bold, bool italics, bool underline)
{
Init(gSexyAppBase,theFace,thePointSize,ANSI_CHARSET,bold,italics,underline,false);
}
SysFont::SysFont(SexyAppBase* theApp, const std::string& theFace, int thePointSize, int theScript, bool bold, bool italics, bool underline)
{
Init(theApp,theFace,thePointSize,theScript,bold,italics,underline,true);
}
void SysFont::Init(SexyAppBase* theApp, const std::string& theFace, int thePointSize, int theScript, bool bold, bool italics, bool underline, bool useDevCaps)
{
mApp = theApp;
HDC aDC = ::GetDC(mApp->mHWnd);
int aHeight = -MulDiv(thePointSize, useDevCaps?GetDeviceCaps(aDC, LOGPIXELSY):96, 72);
mHFont = CreateFontA(aHeight, 0, 0, 0, bold ? FW_BOLD : FW_NORMAL, italics, underline,
false, theScript, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, theFace.c_str());
TEXTMETRIC aTextMetric;
HFONT anOldFont = (HFONT) SelectObject(aDC, mHFont);
GetTextMetrics(aDC, &aTextMetric);
SelectObject(aDC, anOldFont);
ReleaseDC(mApp->mHWnd, aDC);
mHeight = aTextMetric.tmHeight;
mAscent = aTextMetric.tmAscent;
mDrawShadow = false;
mSimulateBold = false;
}
SysFont::SysFont(const SysFont& theSysFont)
{
LOGFONT aLogFont;
GetObject(theSysFont.mHFont, sizeof(LOGFONT), &aLogFont);
mHFont = CreateFontIndirect(&aLogFont);
mApp = theSysFont.mApp;
mHeight = theSysFont.mHeight;
mAscent = theSysFont.mAscent;
mDrawShadow = false;
mSimulateBold = false;
}
SysFont::~SysFont()
{
DeleteObject(mHFont);
}
ImageFont* SysFont::CreateImageFont()
{
int i;
MemoryImage* anImage;
int anImageCharWidth, anImageXOff, anImageYOff;
////////////////////////////////////////////////////
// Step 1: Create image
anImageCharWidth = CharWidth('W')*2;
anImageXOff = anImageCharWidth/4;
anImageYOff = mHeight/2;
int aWidth = 257*anImageCharWidth;
int aHeight = mHeight*2;
BITMAPINFO aBitmapInfo;
memset(&aBitmapInfo,0,sizeof(aBitmapInfo));
BITMAPINFOHEADER &aHeader = aBitmapInfo.bmiHeader;
aHeader.biSize = sizeof(aHeader);
aHeader.biWidth = aWidth;
aHeader.biHeight = -aHeight;
aHeader.biPlanes = 1;
aHeader.biBitCount = 32;
aHeader.biCompression = BI_RGB;
HDC aDC = CreateCompatibleDC(NULL);
DWORD *aBits = NULL;
HBITMAP aBitmap = CreateDIBSection(aDC,&aBitmapInfo,DIB_RGB_COLORS,(void**)&aBits,NULL,0);
HBITMAP anOldBitmap = (HBITMAP)SelectObject(aDC,aBitmap);
HFONT anOldFont = (HFONT)SelectObject(aDC,mHFont);
HBRUSH anOldBrush = (HBRUSH)SelectObject(aDC,GetStockObject(BLACK_BRUSH));
Rectangle(aDC,0,0,aWidth,aHeight);
SetBkMode(aDC, TRANSPARENT);
SetTextColor(aDC, RGB(255,255,255));
int xpos = anImageXOff;
int ypos = anImageYOff;
for (i=0; i<256; i++)
{
char aChar = i;
TextOutA(aDC,xpos,ypos,&aChar,1);
xpos += anImageCharWidth;
}
GdiFlush();
SelectObject(aDC,anOldBrush);
SelectObject(aDC,anOldBitmap);
SelectObject(aDC,anOldFont);
int aSize = aWidth*aHeight;
anImage = new MemoryImage(mApp);
anImage->Create(aWidth,aHeight);
DWORD *src = aBits;
DWORD *dst = anImage->GetBits();
for (i=0; i<aSize; i++)
{
DWORD anAlpha = ((*src++)&0xff)<<24;
*dst++ = anAlpha | 0xFFFFFF;
}
anImage->BitsChanged();
DeleteObject(aBitmap);
////////////////////////////////////////////////////
// Step 2: Create image font
ImageFont *aFont = new ImageFont(anImage);
FontLayer *aFontLayer = &aFont->mFontData->mFontLayerList.back();
aFontLayer->mAscent = mAscent;
aFontLayer->mHeight = mHeight;
for (i=0; i<256; i++)
{
char aChar = i;
aFontLayer->mCharData[(uchar) aChar].mImageRect = Rect(aChar*anImageCharWidth,0,anImageCharWidth,anImage->mHeight);
aFontLayer->mCharData[(uchar) aChar].mWidth = CharWidth(aChar);
aFontLayer->mCharData[(uchar) aChar].mOffset = Point(-anImageXOff,-anImageYOff);
}
aFont->GenerateActiveFontLayers();
aFont->mActiveListValid = true;
return aFont;
}
int SysFont::StringWidth(const SexyString& theString)
{
HDC aDC = ::GetDC(mApp->mHWnd);
HFONT anOldFont = (HFONT)::SelectObject(aDC, mHFont);
int aWidth = 0;
#ifdef _USE_WIDE_STRING
if (CheckFor98Mill())
{
SIZE aSize = { 0, 0 };
GetTextExtentPoint32W(aDC, theString.c_str(), theString.length(), &aSize);
aWidth = int(aSize.cx);
}
else
#endif
{
RECT aRect = {0, 0, 0, 0};
DrawTextEx(aDC, (SexyChar*)theString.c_str(), theString.length(), &aRect, DT_CALCRECT | DT_NOPREFIX, NULL);
aWidth = aRect.right;
}
::SelectObject(aDC, anOldFont);
::ReleaseDC(mApp->mHWnd, aDC);
return aWidth;
}
void SysFont::DrawString(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect& theClipRect)
{
DDImage* aDDImage = dynamic_cast<DDImage*>(g->mDestImage);
if (aDDImage != NULL)
{
LPDIRECTDRAWSURFACE aSurface = aDDImage->GetSurface();
if (aSurface != NULL)
{
HDC aDC;
if (aDDImage->mLockCount > 0)
aDDImage->mSurface->Unlock(NULL);
if ((g->mDestImage == gSexyAppBase->mWidgetManager->mImage) && (gSexyAppBase->Is3DAccelerated()))
gSexyAppBase->mDDInterface->mD3DInterface->Flush();
if (aSurface->GetDC(&aDC) == DD_OK)
{
HFONT anOldFont = (HFONT) SelectObject(aDC, mHFont);
SetBkMode(aDC, TRANSPARENT);
IntersectClipRect(aDC, theClipRect.mX, theClipRect.mY, theClipRect.mX + theClipRect.mWidth, theClipRect.mY + theClipRect.mHeight);
if (mDrawShadow)
{
SetTextColor(aDC, RGB(0,0,0));
TextOut(aDC, theX + g->mTransX+1, theY - mAscent + 1 + g->mTransY+1, theString.c_str(), theString.length());
if (mSimulateBold)
TextOut(aDC, theX + g->mTransX+2, theY - mAscent + 1 + g->mTransY+1, theString.c_str(), theString.length());
}
SetTextColor(aDC, RGB(theColor.GetRed(), theColor.GetGreen(), theColor.GetBlue()));
TextOut(aDC, theX + g->mTransX, theY - mAscent + 1 + g->mTransY, theString.c_str(), theString.length());
if (mSimulateBold)
TextOut(aDC, theX + g->mTransX + 1, theY - mAscent + 1 + g->mTransY, theString.c_str(), theString.length());
::SelectObject(aDC, anOldFont);
aSurface->ReleaseDC(aDC);
aDDImage->DeleteAllNonSurfaceData();
}
if (aDDImage->mLockCount > 0)
aDDImage->mSurface->Lock(NULL, &aDDImage->mLockedSurfaceDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
}
}
else if (g->mDestImage != &Graphics::mStaticImage) // DrawString can be called when not drawing onto an image.
{
HDC aDC = CreateCompatibleDC(NULL);
HFONT anOldFont = (HFONT) SelectObject(aDC, mHFont);
int aWidth = StringWidth(theString);
int aHeight = mHeight;
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biPlanes = 1;
bih.biWidth = aWidth;
bih.biHeight = -aHeight;
bih.biCompression = BI_RGB;
bih.biBitCount = 32;
bih.biSize = sizeof(BITMAPINFOHEADER);
ulong* whiteBits, * blackBits;
HBITMAP whiteBitmap = (HBITMAP)CreateDIBSection(aDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&whiteBits, NULL, 0);
HBITMAP blackBitmap = (HBITMAP)CreateDIBSection(aDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&blackBits, NULL, 0);
RECT rc = { 0, 0, aWidth, aHeight };
#define DRAW_BITMAP(bmp, brush) \
{ \
HBITMAP oldBmp = (HBITMAP) SelectObject(aDC, bmp); \
::FillRect(aDC, &rc, brush); \
SetBkMode(aDC, TRANSPARENT); \
\
if (mDrawShadow) \
{ \
SetTextColor(aDC, RGB(0,0,0)); \
TextOut(aDC, 1, 1, theString.c_str(), theString.length()); \
if (mSimulateBold) \
TextOut(aDC, 2, 1, theString.c_str(), theString.length()); \
} \
SetTextColor(aDC, RGB(theColor.GetRed(), theColor.GetGreen(), theColor.GetBlue())); \
TextOut(aDC, 0, 0, theString.c_str(), theString.length()); \
if (mSimulateBold) \
TextOut(aDC, 1, 0, theString.c_str(), theString.length()); \
\
SelectObject(aDC, oldBmp); \
}
DRAW_BITMAP(whiteBitmap, (HBRUSH)GetStockObject(WHITE_BRUSH));
DRAW_BITMAP(blackBitmap, (HBRUSH)GetStockObject(BLACK_BRUSH));
SelectObject(aDC, anOldFont);
MemoryImage aTempImage;
aTempImage.Create(aWidth, aHeight);
int aCount = aHeight*aWidth;
ulong* ptr1 = whiteBits, *ptr2 = blackBits;
while (aCount > 0)
{
if (*ptr1 == *ptr2)
*ptr1 |= 0xFF000000;
else if ((*ptr1 & 0xFFFFFF) != 0xFFFFFF || (*ptr2 & 0xFFFFFF) != 0x000000) // if not the background of either, it's a 'blend'
{
int ba = 255 + (*ptr2 & 0xFF) - (*ptr1 & 0xFF);
int ga = 255 + ((*ptr2 >> 8) & 0xFF) - ((*ptr1 >> 8) & 0xFF);
int ra = 255 + ((*ptr2 >> 16) & 0xFF) - ((*ptr1 >> 16) & 0xFF);
int aBlue = 255 * (*ptr2 & 0xFF) / ba;
int aGreen = 255 * ((*ptr2 >> 8) & 0xFF) / ga;
int aRed = 255 * ((*ptr2 >> 16) & 0xFF) / ra;
int anAlpha = min(ra, min(ga, ba));
*ptr1 = (aBlue) | (aGreen << 8) | (aRed << 16) | (anAlpha << 24);
}
else *ptr1 &= 0;
ptr1++;
ptr2++;
--aCount;
}
memcpy(aTempImage.GetBits(), whiteBits, aWidth*aHeight*sizeof(ulong));
g->DrawImage(&aTempImage, theX, theY - mAscent);
DeleteObject(whiteBitmap);
DeleteObject(blackBitmap);
DeleteDC(aDC);
}
}
Font* SysFont::Duplicate()
{
return new SysFont(*this);
}