void TextLabel::drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect)
{
    if (rect.width() < 1 || rect.height() < 1) {
        return;
    }

    QPixmap pixmap(rect.size());
    pixmap.fill(Qt::transparent);

    QPainter p(&pixmap);
    p.setPen(painter->pen());

    // Create the alpha gradient for the fade out effect
    QLinearGradient alphaGradient(0, 0, 1, 0);
    alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    if (layout.textOption().textDirection() == Qt::LeftToRight) {
        alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
        alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
    } else {
        alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
        alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
    }

    QFontMetrics fm(layout.font());
    int textHeight = layout.lineCount() * fm.lineSpacing();

    QPointF position(0, (rect.height() - textHeight) / 2);
    QList<QRect> fadeRects;
    int fadeWidth = 30;

    // Draw each line in the layout
    for (int i = 0; i < layout.lineCount(); i++) {
        QTextLine line = layout.lineAt(i);
        line.draw(&p, position);

        // Add a fade out rect to the list if the line is too long
        if (line.naturalTextWidth() > rect.width())
        {
            int x = int(qMin(line.naturalTextWidth(), (qreal)pixmap.width())) - fadeWidth;
            int y = int(line.position().y() + position.y());
            QRect r = QStyle::visualRect(layout.textOption().textDirection(), pixmap.rect(),
                                         QRect(x, y, fadeWidth, int(line.height())));
            fadeRects.append(r);
        }
    }

    // Reduce the alpha in each fade out rect using the alpha gradient
    if (!fadeRects.isEmpty()) {
        p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
        foreach (const QRect &rect, fadeRects) {
            p.fillRect(rect, alphaGradient);
        }
Exemple #2
0
void tst_QTextFormat::testTabsUsed()
{
    QTextDocument doc;
    QTextCursor cursor(&doc);

    QList<QTextOption::Tab> tabs;
    QTextBlockFormat format;
    QTextOption::Tab tab;
    tab.position = 100;
    tabs.append(tab);
    format.setTabPositions(tabs);
    cursor.mergeBlockFormat(format);
    cursor.insertText("foo\tbar");
    //doc.setPageSize(QSizeF(200, 200));
    doc.documentLayout()->pageCount(); // force layout;

    QTextBlock block = doc.begin();
    QTextLayout *layout = block.layout();
    QVERIFY(layout);
    QCOMPARE(layout->lineCount(), 1);
    QTextLine line = layout->lineAt(0);
    QCOMPARE(line.cursorToX(4), 100.);

    QTextOption option = layout->textOption();
    QCOMPARE(option.tabs().count(), tabs.count());

}
Exemple #3
0
void TestDocumentLayout::placeAnchoredFrame()
{
    initForNewTest(QString());
    MockShape *picture = new MockShape();
    picture->setSize(QSizeF(100, 100));
    KTextAnchor *anchor = new KTextAnchor(picture);
    anchor->setOffset(QPointF(23, 45));
    QTextCursor cursor(doc);

    KInlineTextObjectManager *manager = new KInlineTextObjectManager();
    layout->setInlineTextObjectManager(manager);
    MockLayoutState *state = new MockLayoutState(doc);
    layout->setLayout(state);
    state->shape = shape1;
    QCOMPARE(doc->begin().text().length(), 0);
    manager->insertInlineObject(cursor, anchor);
    QCOMPARE(doc->begin().text().length(), 1);
    QCOMPARE(cursor.position(), 1);

    shape1->setPosition(QPointF(300, 300));
    layout->layout();
    QCOMPARE(picture->parent(), shape1);
    QCOMPARE(picture->position(), QPointF(23, 59.4));

    cursor.setPosition(0);
    cursor.insertText("foo"); // moves my anchors slightly to the right/down and gives line height
    layout->layout();
    QCOMPARE(picture->parent(), shape1);
    QPointF newPos = picture->position();
    QVERIFY(newPos.x() > 23);
    QVERIFY(newPos.y() > 45); // it adds the baseline now

    cursor.movePosition(QTextCursor::End);
    cursor.insertText("\nNew Line\nAnd another");

    layout->layout();
    QCOMPARE(picture->position(), newPos);

    QTextLayout *firstLineLayout = doc->begin().layout();
    QTextOption option = firstLineLayout->textOption();
    option.setAlignment(Qt::AlignHCenter);
    firstLineLayout->setTextOption(option);

    layout->layout();
    QTextLine first = doc->begin().layout()->lineAt(0);
    QVERIFY(first.isValid());
    QVERIFY(first.naturalTextRect().x() > 10);
    newPos.setX(newPos.x() + first.naturalTextRect().x()); // text is moved due to alignment
    QCOMPARE(picture->position(), newPos);

    anchor->setOffset(QPointF());
    anchor->setAlignment(KTextAnchor::Left);
    anchor->setAlignment(KTextAnchor::TopOfParagraph);
    layout->layout();
    // image is 100 wide, now centered in a parent of 200 so X = 50
    QCOMPARE(picture->position(), QPointF(50, 0));
}
Exemple #4
0
int KTextDocumentLayout::hitTestIterated(QTextFrame::iterator begin, QTextFrame::iterator end, const QPointF &point, Qt::HitTestAccuracy accuracy) const
{
    int position = -1;
    QTextFrame::iterator it = begin;
    for (it = begin; it != end; ++it) {
        QTextBlock block = it.currentBlock();
        QTextTable *table = qobject_cast<QTextTable*>(it.currentFrame());
        QTextFrame *subFrame = it.currentFrame();

        if (table) {
            QTextTableCell cell = m_state->hitTestTable(table, point);
            if (cell.isValid()) {
                position = hitTestIterated(cell.begin(), cell.end(), point,
                                accuracy);
                if (position == -1)
                    position = cell.lastPosition();
                return position;
            }
            continue;
        } else if (subFrame) {
            position = hitTestIterated(subFrame->begin(), subFrame->end(), point, accuracy);
            if (position != -1)
                return position;
            continue;
        } else {
            if (!block.isValid())
                continue;
        }
        // kDebug(32500) <<"hitTest[" << point.x() <<"," << point.y() <<"]";
        QTextLayout *layout = block.layout();
        if (point.y() > layout->boundingRect().bottom()) {
            // just skip this block. position = block.position() + block.length() - 1;
            continue;
        }
        for (int i = 0; i < layout->lineCount(); i++) {
            QTextLine line = layout->lineAt(i);
            // kDebug(32500) <<" + line[" << line.textStart() <<"]:" << line.y() <<"-" << line.height();
            if (point.y() > line.y() + line.height()) {
                position = line.textStart() + line.textLength();
                continue;
            }
            if (accuracy == Qt::ExactHit && point.y() < line.y()) // between lines
                return -1;
            if (accuracy == Qt::ExactHit && // left or right of line
                    (point.x() < line.x() || point.x() > line.x() + line.width()))
                return -1;
            if (point.x() > line.width() && layout->textOption().textDirection() == Qt::RightToLeft) {
                // totally right of RTL text means the position is the start of the text.
                return block.position() + line.textStart();
            }
            return block.position() + line.xToCursor(point.x());
        }
    }
    return -1;
}