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