You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
5.4 KiB
C++

#include <qbitmap.h>
#include "qwt3d_label.h"
using namespace Qwt3D;
bool Label::devicefonts_ = false;
Label::Label()
{
init();
}
Label::Label(const QString & family, int pointSize, int weight, bool italic)
{
init(family, pointSize, weight, italic);
}
void Label::init(const QString & family, int pointSize, int weight, bool italic)
{
init();
font_ = QFont(family, pointSize, weight, italic );
}
void Label::init()
{
beg_ = Triple(0.0, 0.0, 0.0);
end_ = beg_;
pos_ = beg_;
setColor(0,0,0);
pm_ = QPixmap(0, 0);
font_ = QFont();
anchor_ = BottomLeft;
gap_ = 0;
flagforupdate_ = true;
}
void Label::useDeviceFonts(bool val)
{
devicefonts_ = val;
}
void Label::setFont(const QString & family, int pointSize, int weight, bool italic)
{
font_ = QFont(family, pointSize, weight, italic );
flagforupdate_ = true;
}
void Label::setString(QString const& s)
{
text_ = s;
flagforupdate_ = true;
}
void Label::setColor(double r, double g, double b, double a)
{
Drawable::setColor(r,g,b,a);
flagforupdate_ = true;
}
void Label::setColor(Qwt3D::RGBA rgba)
{
Drawable::setColor(rgba);
flagforupdate_ = true;
}
/**
example:
\verbatim
Anchor TopCenter (*) resp. BottomRight(X)
+----*----+
| Pixmap |
+---------X
\endverbatim
*/
void Label::setPosition(Triple pos, ANCHOR a)
{
anchor_ = a;
pos_ = pos;
}
void Label::setRelPosition(Tuple rpos, ANCHOR a)
{
double ot = 0.99;
getMatrices(modelMatrix, projMatrix, viewport);
beg_ = relativePosition(Triple(rpos.x, rpos.y, ot));
setPosition(beg_, a);
}
void Label::update()
{
QPainter p;
QFontMetrics fm(font_);
QFontInfo info(font_);
QRect r = QRect(QPoint(0,0),fm.size(Qwt3D::SingleLine, text_));//fm.boundingRect(text_) misbehaviour under linux;
#if QT_VERSION < 0x040000
r.moveBy(0, -r.top());
#else
r.translate(0, -r.top());
#endif
pm_ = QPixmap(r.width(), r.bottom());
if (pm_.isNull()) // else crash under linux
{
r = QRect(QPoint(0,0),fm.size(Qwt3D::SingleLine, QString(" "))); // draw empty space else //todo
#if QT_VERSION < 0x040000
r.moveBy(0, -r.top());
#else
r.translate(0, -r.top());
#endif
pm_ = QPixmap(r.width(), r.bottom());
}
QBitmap bm(pm_.width(),pm_.height());
bm.fill(Qt::color0);
p.begin( &bm );
p.setPen(Qt::color1);
p.setFont(font_);
p.drawText(0,r.height() - fm.descent() -1 , text_);
p.end();
pm_.setMask(bm);
// avoids uninitialized areas in some cases
#if QT_VERSION < 0x040000
pm_.fill();
#endif
p.begin( &pm_ );
p.setFont( font_ );
p.setPen( Qt::SolidLine );
p.setPen( GL2Qt(color.r, color.g, color.b) );
p.drawText(0,r.height() - fm.descent() -1 , text_);
p.end();
#if QT_VERSION < 0x040000
buf_ = pm_.convertToImage();
#else
buf_ = pm_.toImage();
#endif
tex_ = QGLWidget::convertToGLFormat( buf_ ); // flipped 32bit RGBA ?
}
/**
Adds an additional shift to the anchor point. This happens in a more or less intelligent manner
depending on the nature of the anchor:
\verbatim
anchor type shift
left aligned -->
right aligned <--
top aligned top-down
bottom aligned bottom-up
\endverbatim
The unit is user space dependend (one pixel on screen - play around to get satisfying results)
*/
void Label::adjust(int gap)
{
gap_ = gap;
}
void Label::convert2screen()
{
Triple start = World2ViewPort(pos_);
switch (anchor_)
{
case BottomLeft :
beg_ = pos_;
break;
case BottomRight:
beg_ = ViewPort2World(start - Triple(width() + gap_, 0, 0));
break;
case BottomCenter:
beg_ = ViewPort2World(start - Triple(width() / 2, -gap_, 0));
break;
case TopRight:
beg_ = ViewPort2World(start - Triple(width() + gap_, height(), 0));
break;
case TopLeft:
beg_ = ViewPort2World(start - Triple(-gap_, height(), 0));
break;
case TopCenter:
beg_ = ViewPort2World(start - Triple(width() / 2, height() + gap_, 0));
break;
case CenterLeft:
beg_ = ViewPort2World(start - Triple(-gap_, height() / 2, 0));
break;
case CenterRight:
beg_ = ViewPort2World(start - Triple(width() + gap_, height() / 2, 0));
break;
case Center:
beg_ = ViewPort2World(start - Triple(width() / 2, height() / 2, 0));
break;
default:
break;
}
start = World2ViewPort(beg_);
end_ = ViewPort2World(start + Triple(width(), height(), 0));
}
void Label::draw()
{
if (flagforupdate_)
{
update();
flagforupdate_ = false;
}
if (buf_.isNull())
return;
GLboolean b;
GLint func;
GLdouble v;
glGetBooleanv(GL_ALPHA_TEST, &b);
glGetIntegerv(GL_ALPHA_TEST_FUNC, &func);
glGetDoublev(GL_ALPHA_TEST_REF, &v);
glEnable (GL_ALPHA_TEST);
glAlphaFunc (GL_NOTEQUAL, 0.0);
convert2screen();
glRasterPos3d(beg_.x, beg_.y, beg_.z);
int w = tex_.width();
int h = tex_.height();
if (devicefonts_)
{
drawDeviceText(QWT3DLOCAL8BIT(text_), "Courier", font_.pointSize(), pos_, color, anchor_, gap_);
}
else
{
drawDevicePixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex_.bits());
// glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex_.bits());
}
glAlphaFunc(func,v);
Enable(GL_ALPHA_TEST, b);
}
double Label::width() const
{
return pm_.width();
}
double Label::height() const
{
return pm_.height();
}