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.
291 lines
8.7 KiB
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(®ion); // region painter
|
|
|
|
TQBitmap regionMask(
|
|
(stringWidth > wide ? stringWidth : wide),
|
|
mHeight, true); // fully transparent mask
|
|
TQPainter mp(®ionMask); // 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( ®ionMask );
|
|
|
|
// 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(®ion, ®ionMask, 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);
|
|
}
|