You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/modules/kjofol-skin/kjfont.cpp

291 lines
8.7 KiB

/***************************************************************************
kjfont.cpp
--------------------------------------
Font-Handling of KJöfol
Creates pixmaps of strings using the supplied font-pixmap
--------------------------------------
Maintainer: Stefan Gehn <sgehn@gmx.net>
***************************************************************************/
#include "kjfont.h"
#include "kjloader.h"
#include "kjwidget.h"
#include "kjprefs.h"
#include <kdebug.h>
#include <kglobalsettings.h>
#include <tqimage.h>
#include <tqpainter.h>
/*******************************************
* KJFont
*******************************************/
KJFont::KJFont(const TQString &prefix, KJLoader *parent) : mTextMask(0), mTransparentRGB(0)
{
// kdDebug(66666) << "KJFont::KJFont(const TQString &prefix, KJLoader *parent)" << prefix.latin1() << endl;
if (prefix=="timefont")
{
mString[0]="0123456789: ";
mString[1]=mString[2]="";
mNullChar=' ';
}
else if ( (prefix=="volumefont") || (prefix=="pitchfont") )
{
mString[0]="0123456789% ";
mString[1]=mString[2]="";
mNullChar=' ';
}
else
{
mString[0]="abcdefghijklmnopqrstuvwxyz\"@";
mString[1]="0123456789;_:()-'!_+\\/[]*&%.=$#";
mString[2]="åöä?*, ";
mNullChar=' ';
}
mText = parent->pixmap(parent->item(prefix+"image")[1]);
if ( parent->exist(prefix+"size") )
{
mWidth = parent->item(prefix+"size")[1].toInt();
mHeight = parent->item(prefix+"size")[2].toInt();
}
else // try to load the font even we are missing important settings
{ // this still can cause crashes!
kdDebug(66666) << "font height/width missing, this skin might crash noatun!" << endl;
mWidth = mText.width() / strlen(mString[0]);
if ( (prefix=="timefont") || (prefix=="volumefont") || (prefix=="pitchfont") )
mHeight = mText.height();
else
mHeight = mText.height()/3;
}
// kdDebug(66666) << prefix << " h: " << mHeight << " w: " << mWidth << endl;
// fix for wrong numbers in rc (a skin named steelforged needs that)
if ( mHeight > mText.height() )
mHeight = mText.height();
// Stupid Skin authors tend to forget keys :/
if ( parent->exist(prefix+"spacing") )
mSpacing = parent->item(prefix+"spacing")[1].toInt();
else
mSpacing = 0; // FIXME: What's default for this in kjöfol???
if ( parent->exist(prefix+"transparent") )
mTransparent = (bool)parent->item(prefix+"transparent")[1].toInt();
else
mTransparent = true; // transparency seems to be default in kjöfol
// define color in font that will be transparent later on
if ( mTransparent )
{
TQImage ibackground = mText.convertToImage();
mTransparentRGB = ibackground.pixel( ibackground.width()-1, ibackground.height()-1 );
// kdDebug(66666) << "color (" << tqRed(mTransparentRGB) << "," << tqGreen(mTransparentRGB) << "," << tqBlue(mTransparentRGB) << ") will be transparent for " << prefix.latin1() << endl;
mTextMask = KJWidget::getMask(ibackground,mTransparentRGB);
}
mUseSysFont = KJLoader::kjofol->prefs()->useSysFont();
sysFontMetrics = 0L;
if (mUseSysFont)
recalcSysFont();
}
void KJFont::recalcSysFont(void)
{
// kdDebug(66666) << k_funcinfo << "called." << endl;
mUseSysFont = KJLoader::kjofol->prefs()->useSysFont();
if (!mUseSysFont)
return;
sysFont = TQFont(KJLoader::kjofol->prefs()->sysFont());
sysFont.setStyleStrategy( TQFont::NoAntialias );
if ( sysFontMetrics )
delete sysFontMetrics;
sysFontColor = KJLoader::kjofol->prefs()->sysFontColor();
// kdDebug(66666) << "mHeight=" << mHeight << endl;
int fSize;
for(fSize = mHeight; fSize>=4; fSize--)
{
sysFont.setPixelSize ( fSize );
sysFontMetrics = new TQFontMetrics(sysFont);
// kdDebug(66666) << "wanted fSize=" << fSize << ", metric h=" << sysFontMetrics->height() << endl;
// either found a small enough font or found no proper font at all
if ( sysFontMetrics->height() <= mHeight || fSize==4 )
{
// kdDebug(66666) << "stopping @ fSize=" << fSize << ", metric h=" << sysFontMetrics->height() << endl;
return;
}
delete sysFontMetrics;
}
}
TQPixmap KJFont::draw(const TQCString &str, int wide, const TQPoint &pos) const
{
if ( mUseSysFont )
return drawSysFont(str,wide,pos);
else
return drawPixmapFont(str,wide,pos);
}
TQPixmap KJFont::drawSysFont(const TQCString &s, int wide, const TQPoint &pos) const
{
// kdDebug(66666) << k_funcinfo << "BEGIN, s='" << s << "'" << endl;
TQPoint to(pos);
TQString string(s);
int stringWidth = sysFontMetrics->width( string );
// kdDebug(66666) << "final metrics; w=" << stringWidth << ", h=" << sysFontMetrics->height() << endl;
TQPixmap region(
(stringWidth > wide ? stringWidth : wide),
mHeight);
TQPainter rp(&region); // region painter
TQBitmap regionMask(
(stringWidth > wide ? stringWidth : wide),
mHeight, true); // fully transparent mask
TQPainter mp(&regionMask); // mask painter
// kdDebug(66666) << "region; w=" << region.width() << ", h=" << region.height() << endl;
int freeSpace=0;
// center string into pixmap if its chars won't fill the whole pixmap
if ( stringWidth < wide )
{
freeSpace = wide - stringWidth;
mp.fillRect ( to.x(), 0, (freeSpace/2), mHeight, TQt::color0 );
to += TQPoint ( (freeSpace/2), 0 );
// kdDebug(66666) << "centering text, freeSpace=" << freeSpace << endl;
}
rp.setFont(sysFont);
rp.setPen(sysFontColor);
rp.drawText(to.x(), to.y(), region.width()-freeSpace, mHeight, TQt::AlignLeft|TQt::AlignTop, string);
mp.setFont(sysFont);
mp.setPen(TQt::color1);
mp.drawText(to.x(), to.y(), region.width()-freeSpace, mHeight, TQt::AlignLeft|TQt::AlignTop, string);
to += TQPoint(region.width()-freeSpace,0);
// kdDebug(66666) << "text width=" << region.width()-freeSpace << endl;
if (freeSpace > 0)
{
mp.fillRect ( to.x(), 0, (freeSpace/2), mHeight, TQt::color0 );
to += TQPoint ( (freeSpace/2), 0 );
// kdDebug(66666) << "centering text, freeSpace=" << freeSpace << endl;
}
region.setMask( regionMask );
// kdDebug(66666) << "width: " << wide << "|end after drawing: " << to.x() << endl;
// kdDebug(66666) << k_funcinfo << "END" << endl << endl;
return region;
}
TQPixmap KJFont::drawPixmapFont(const TQCString &str, int wide, const TQPoint &pos) const
{
// kdDebug(66666) << k_funcinfo << "BEGIN" << endl;
TQPoint to(pos);
TQCString string = str.lower();
TQPixmap region(
(string.length()*mWidth+string.length()*mSpacing > (unsigned int)wide
? string.length()*mWidth+string.length()*mSpacing : wide),
mHeight);
TQBitmap regionMask(
(string.length()*mWidth+string.length()*mSpacing > (unsigned int)wide
? string.length()*mWidth+string.length()*mSpacing : wide),
mHeight, true); // fully transparent mask
TQPainter mask( &regionMask );
// kdDebug(66666) << "draw: {" << str << "}" << endl;
int freeSpace=0;
// center string into pixmap if its chars won't fill the whole pixmap
if ( string.length()*mWidth+string.length()*mSpacing < (unsigned int)wide )
{
freeSpace = wide - string.length()*mWidth+string.length()*mSpacing;
mask.fillRect ( to.x(), 0, (freeSpace/2), mHeight, TQt::color0 );
to += TQPoint ( (freeSpace/2), 0 );
}
// kdDebug(66666) << k_funcinfo << "pixmap width=" << region.width() << endl;
// draw every char and add spacing in between these chars if defined
unsigned int stringLength(string.length());
for ( unsigned int charPos=0; charPos < stringLength; charPos++ )
{
char c = string[charPos]; // the character to be drawn next
drawCharacter(&region, &regionMask, to, c);
to += TQPoint(mWidth, 0);
// draw according to "spacing"
if ( (charPos < string.length()-1) && mSpacing > 0 )
{ // make the spacing-area transparent
mask.fillRect ( to.x(), 0, mSpacing, mHeight, TQt::color0 );
to += TQPoint ( mSpacing, 0 );
}
}
if (freeSpace > 0)
{
mask.fillRect ( to.x(), 0, (freeSpace/2), mHeight, TQt::color0 );
to += TQPoint ( (freeSpace/2), 0 );
}
region.setMask( regionMask );
// kdDebug(66666) << "width: " << wide << "|end after drawing: " << to.x() << endl;
return region;
}
void KJFont::drawCharacter(TQPixmap *dev, TQBitmap *devMask, const TQPoint &to, char c) const
{
TQPoint src=charSource(c);
int x=src.x();
int y=src.y();
int xs=mWidth;
int ys=mHeight;
bitBlt(dev, to, &mText, TQRect(x,y,xs,ys), TQt::CopyROP);
// bitBlt mask for transparency
if ( mTransparent )
{
bitBlt(devMask, to, &mTextMask, TQRect(x,y,xs,ys), TQt::OrROP);
}
else // fill mask
{
TQPainter tempPainter (devMask);
tempPainter.fillRect ( to.x(), 0, xs,ys, TQt::color1 );
}
}
// needed for strchr
#include <string.h>
// searches for top/left coordinate of a given character inside the font-pixmap
TQPoint KJFont::charSource(char c) const
{
for (int i=0; i<3; i++)
{
const char *pos = strchr(mString[i], c);
if (!pos) continue;
return TQPoint(mWidth*((int)(pos-mString[i])), mHeight*i);
}
return charSource(mNullChar);
}