PDA

View Full Version : Problem with QPainter drawText() not rendering text at large coordinates



cgomez116
19th September 2009, 02:35
I am using painter->drawText() inside a for loop in a QGraphicsItem's paint method, and the text is being rendered till it gets to a certain coordinate where it stops rendering. It looks to be because the the value of the coordinate is too large? Interestingly the drawLine() has no problem with the coordinates above where the drawText fails and rendered correctly.




//-------------------------------------------------------------------------------
// TimeRulerItem::paint()
//
//-------------------------------------------------------------------------------
void TimeRulerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);

if(option->levelOfDetail < 0.05) {
return;
}

QColor fillColor = (option->state & QStyle::State_Selected) ? Bg.dark(150) : Bg;

if (option->state & QStyle::State_MouseOver)
fillColor = fillColor.light(125);

QColor color;
qreal width;
if (option->state & QStyle::State_MouseOver) {
color = QColor(Qt::yellow);
width = 1.0;
} else {
color = Fg;
width = 0.75;
}

painter->setFont(QApplication::font());
painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100)));
painter->setPen(QPen(color, width));

const QRectF exposed = option->exposedRect;

qDebug() << "\n\n\n";

qDebug() << "viewport:" << painter->viewport();
qDebug() << "window:" << painter->window();

qDebug() << "exposed:" << exposed;

const qreal ex_top = exposed.top();
const qreal ex_bot = exposed.bottom();
const qreal ex_left = exposed.left();
const qreal ex_right = exposed.right();
const qreal ex_height = exposed.height();
const qreal ex_width = exposed.width();

const qint64 num_ticks = EndTime - StartTime;

const qint64 start_tick = ex_left/TICK_WIDTH;
const qint64 end_tick = ex_right/TICK_WIDTH;

qDebug() << "start_tick:" << start_tick
<< ", end_tick:" << end_tick;

for(qint64 i = 0; i <= end_tick-start_tick; i++) {
qDebug() << "Drawing tick:" << i;

const qint64 time = i+StartTime;
const qint64 time_mod_10 = time%10;
qDebug() << " time:" << time << ", time_mod_10:" << time_mod_10;

// Draw the tick mod 10 lines:
if(time%10 == 0) painter->drawLine(i*TICK_WIDTH, TICK_HEIGHT, i*TICK_WIDTH, -2*TICK_HEIGHT);

// Draw tick mod 10
painter->setPen(QPen(color, width));
const QString time_str = QString::number(time);
const QString time_mod_10_str = QString::number(time_mod_10);
qDebug() << " time:" << time_str << ", time_mod_10:" << time_mod_10_str;

const qint64 x = i*TICK_WIDTH;
const qint64 x_1 = (i*TICK_WIDTH) + 1;
qDebug() << " x:" << x << ", x_1:" << x_1;

const qreal fx = x;
const qreal fx_1 = x_1;
qDebug() << " fx:" << fx << ", fx_1:" << fx_1;

const QPoint pt = QPoint(x , -1);
const QPoint pt_1 = QPoint(x_1, 11);
qDebug() << " pt:" << pt << ", pt_1:" << pt_1;

if(time%10 == 0) painter->drawText(pt, time_str);

// Draw tick
painter->drawText(pt_1, time_mod_10_str);
}
}

cgomez116
20th September 2009, 02:08
I have confirmed this is related to bug 192573, and in fact is the exact location of offet 33554443. It looks like this is a bug they are not going to fix, they do say there is a workaround, but I do not know what the workaround is. If any one can help with the workaround, it would be greatly appreciated.

Thanks in advance.

http://qt.nokia.com/developer/task-tracker/index_html?method=entry&id=192573

192573 - Text not rendered after a certain horizontal offset
Report type Bug Status? Closed Resolution? Won't fix
Product Qt Functional area Text handling Version found 4.3.2
Priority? 2 Scheduled for? Some future release

Description

QPainter::drawText() does not render text after a certain horizontal offset, the magic number seems to be (or is close to) 33554443.
If a QPainter is translated beyond this point and one attempts to draw text, it won't be visible.

Won't fix reason: The magic number is the max range of the QFixed (uses a 26.6 notation) type we use to store the glyph positions internally in Qt. Fixing this would mean rewriting all of the text internals in Qt. That we won't do. However it's possible to work around this by manually transforming the text position before the drawText() call.
History

2007-12-21 14:38 - Entry created: Task status changed to 'Open', Resolution set to 'Pending', Version found set to '4.3.2', Version for fix set to 'Not scheduled', Priority changed to 'No Priority'
2008-02-14 09:30 - Version for fix set to 'Some future release'
2008-02-14 09:30 - Priority changed to '2'
2008-11-04 13:58 - Task status changed to 'Closed'
2008-11-04 13:58 - Resolution set to 'Won't fix'

cgomez116
20th September 2009, 03:59
I found a work around for this, as suggested in bug 192573:
http://qt.nokia.com/developer/task-tracker/index_html?method=entry&id=192573

I used the worldTransform to translate the painter, so that I can use position offsets in drawText() that start at 0.



void TimeRulerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);

if(option->levelOfDetail < 0.05) return;

QColor fillColor = (option->state & QStyle::State_Selected) ? Bg.dark(150) : Bg;

if (option->state & QStyle::State_MouseOver)
fillColor = fillColor.light(125);

QColor color;
qreal width;
if (option->state & QStyle::State_MouseOver) {
color = QColor(Qt::yellow);
width = 1.0;
} else {
color = Fg;
width = 0.75;
}

painter->setFont(QApplication::font());
painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100)));
painter->setPen(QPen(color, width));

const QRectF exposed = option->exposedRect;
const qreal ex_left = exposed.left();
const qreal ex_right = exposed.right();

const qint64 start_tick = (qint64)ex_left/TICK_WIDTH;
const qint64 end_tick = (qint64)ex_right/TICK_WIDTH;

const qint64 n_tick = start_tick*TICK_WIDTH;
const qint64 n_tick_1 = n_tick - 1;

QTransform wt = painter->worldTransform();
wt.translate(n_tick_1, 0);
painter->setWorldTransform(wt);

for(qint64 i = 0; i <= end_tick-start_tick; i++) {
const qint64 time = i + start_tick + StartTime;
const qint64 time_mod_10 = time%10;

// Draw the tick mod 10 lines:
if(time%10 == 0) painter->drawLine(i*TICK_WIDTH, TICK_HEIGHT, i*TICK_WIDTH, -2*TICK_HEIGHT);

if(option->levelOfDetail < 0.5) return;

// Draw tick line every 10 ticks:
painter->setPen(QPen(color, width));
const QString time_str = QString::number(time);
const QString time_mod_10_str = QString::number(time_mod_10);

const qint64 x = i*TICK_WIDTH;
const qint64 x_1 = (i*TICK_WIDTH) + 1;

const QPoint pt = QPoint(x , -1);
const QPoint pt_1 = QPoint(x_1, 11);

// Draw full time every 10 ticks:
if(time%10 == 0) painter->drawText(pt, time_str);

// Draw time mod 10 (tick number):
painter->drawText(pt_1, time_mod_10_str);
}
}