Exemple #1
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;
}
Exemple #2
0
void TestDocumentLayout::testRightToLeftList()
{
    initForNewTest("a\nb\nc");
    KoParagraphStyle h1;
    h1.setTextProgressionDirection(KoText::RightLeftTopBottom);
    m_styleManager->add(&h1);
    KoListStyle listStyle;
    KoListLevelProperties llp = listStyle.levelProperties(1);
    llp.setStyle(KoListStyle::DecimalItem);
    listStyle.setLevelProperties(llp);
    h1.setListStyle(&listStyle);

    QTextBlock block = m_doc->begin();
    h1.applyStyle(block);
    block = block.next();
    h1.applyStyle(block);
    block = block.next();
    h1.applyStyle(block);
    block = block.next();

    m_layout->layout();

    block = m_doc->begin();
    while (block.isValid()) {
        KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData());
        QVERIFY(data);
        QVERIFY(data->counterWidth() > 2);
        QVERIFY(data->counterPosition().x() > 100);
        QTextLine line = block.layout()->lineAt(0);
        QVERIFY(line.isValid());
        QCOMPARE(line.x(), (qreal)0);
        QCOMPARE(line.width() + data->counterWidth() + data->counterSpacing(), (qreal)200);
        block = block.next();
    }
}
QRect StyleHelper::drawText(QPainter* p, const QRect& rc, QString& str, int nLines,
                          int nFlags, const QColor& color, const QFont& font, bool bElided)
{
    if (str.isEmpty()) {
        qDebug() << "[WARNING]: the text should not be empty when drawing!";
        return QRect();
    }

    QFontMetrics fm(font);
    if (rc.height() < (fm.height() + fm.leading()) * nLines) {
        qDebug() << "[WARNING]: space is not enough for drawing! text: " << str.left(30) << "...";
    }

    //if (rc.width() * nLines < fm.width(str)) {
    //    qDebug() << "[WARNING]: width should bigger than font metrics when drawing! text:" << str.left(30) << "...";
    //}

    p->save();
    p->setPen(color);
    p->setFont(font);

    int nWidth = 0;
    int nHeight = 0;
    int nHeightLine = p->fontMetrics().height() + leading();

    QRect rcRet(rc.x(), rc.y(), rc.width(), nHeightLine);
    rcRet.adjust(margin(), 0, -margin(), 0);

    QTextLayout textLayout(str, p->font());
    QTextOption opt = textLayout.textOption();
    opt.setWrapMode(QTextOption::WrapAnywhere);
    textLayout.setTextOption(opt);

    textLayout.beginLayout();
    while (nLines) {
        QTextLine line = textLayout.createLine();
        if (!line.isValid()) {
            break;
        }

        line.setLineWidth(rcRet.width());

        QString lineText;
        if (nLines == 1 && bElided) { // the last line
            lineText = p->fontMetrics().elidedText(str, Qt::ElideRight, rcRet.width());
            nWidth = qMax<int>(p->fontMetrics().width(lineText), nWidth);
        } else {
            lineText = str.left(line.textLength());
            nWidth = qMax<int>(line.width(), nWidth);
        }

        str.remove(0, line.textLength());
        p->drawText(rcRet, nFlags, lineText);

        nHeight += nHeightLine;
        rcRet.setRect(rc.x(), rc.y() + nHeight, nWidth, nHeightLine);
        rcRet.adjust(margin(), 0, -margin(), 0);

        nLines--;
    }
    textLayout.endLayout();

    rcRet.setRect(rc.x() + margin(), rc.y(), nWidth + margin(), nHeight);
    //rcRet.adjust(margin(), 0, -margin(), 0);

    p->restore();

    return rcRet;
}
void TestTableLayout::testBasicLayout()
{
    QList<KoTableColumnStyle *> columnStyles;
    QList<KoTableRowStyle *> rowStyles;
    QMap<QPair<int, int>, KoTableCellStyle *> cellStyles;
    QMap<QPair<int, int>, QString> cellTexts;
    cellTexts.insert(qMakePair(0, 0), "Cell 1");
    cellTexts.insert(qMakePair(0, 1), "Cell 2");
    cellTexts.insert(qMakePair(1, 0), "Cell 3");
    cellTexts.insert(qMakePair(1, 1), "Cell 4");

    initTest(2, 2, 0, columnStyles, rowStyles, cellStyles, cellTexts);

    m_layout->layout();

    // Check that the table and layout data was correctly added to the table data map.
    QVERIFY(m_textLayout->m_tableLayout.m_tableLayoutDataMap.contains(m_table));
    TableLayoutData *tableLayoutData = m_textLayout->m_tableLayout.m_tableLayoutDataMap.value(m_table);
    QVERIFY(tableLayoutData);

    // Check table dimensions are correct.
    QCOMPARE(tableLayoutData->m_rowPositions.size(), 2);
    QCOMPARE(tableLayoutData->m_rowHeights.size(), 2);
    QCOMPARE(tableLayoutData->m_tableRects.last().columnPositions.size(), 2);
    QCOMPARE(tableLayoutData->m_tableRects.last().columnWidths.size(), 2);

    // Check cell bounding rectangles.

    /*
     * Cell 0, 0 rules:
     *   x = 0 (no borders/margins/paddings)
     *   y = 0 (no borders/margins/paddings)
     *   width = 200/2 = 100 (table width/column count)
     *   height = 1 * 14.4 = 14.4 (number of lines * line height)
     */
    QTextTableCell cell1 = m_table->cellAt(0, 0);
    QCOMPARE(m_textLayout->m_tableLayout.cellBoundingRect(cell1), QRectF(0, 0, 100, 14.4));

    /*
     * Cell 0, 1 rules:
     *   x = 100 (table width/column count)
     *   y = 0 (no borders/margins/paddings)
     *   width = 200/2 = 100 (table width/column count)
     *   height = 1 * 14.4 = 14.4 (number of lines * line height)
     */
    QTextTableCell cell2 = m_table->cellAt(0, 1);
    QCOMPARE(m_textLayout->m_tableLayout.cellBoundingRect(cell2), QRectF(100, 0, 100, 14.4));

    /*
     * Cell 1, 0 rules:
     *   x = 0 (no borders/margins/paddings)
     *   y = 14.4 (line height)
     *   width = 200/2 = 100 (table width/column count)
     *   height = 1 * 14.4 = 14.4 (number of lines * line height)
     */
    QTextTableCell cell3 = m_table->cellAt(1, 0);
    QCOMPARE(m_textLayout->m_tableLayout.cellBoundingRect(cell3), QRectF(0, 14.4, 100, 14.4));

    /*
     * Cell 1, 1 rules:
     *   x = 100 (table width/column count)
     *   y = 14.4 (line height)
     *   width = 200/2 = 100 (table width/column count)
     *   height = 1 * 14.4 = 14.4 (number of lines * line height)
     */
    QTextTableCell cell4 = m_table->cellAt(1, 1);
    QCOMPARE(m_textLayout->m_tableLayout.cellBoundingRect(cell4), QRectF(100, 14.4, 100, 14.4));

    // Check position of blocks in cells.

    QTextBlock block1 = cell1.firstCursorPosition().block();
    QCOMPARE(block1.position(), 1);
    QVERIFY(block1.layout());
    QCOMPARE(block1.layout()->lineCount(), 1);
    QTextLine line = block1.layout()->lineAt(0);
    QCOMPARE(line.width(), 100.);
    QCOMPARE(line.position(), QPointF());

    /*
     * Blocks in cell 0,1 rules:
     *   Position      Content      Layout bounding rect
     *   8             "Cell 2"     100, 0 100x?
     */
    QTextBlock block2 = cell2.firstCursorPosition().block();
    QCOMPARE(block2.position(), 8);
    QVERIFY(block2.layout());
    QCOMPARE(block2.layout()->lineCount(), 1);
    line = block2.layout()->lineAt(0);
    QCOMPARE(line.width(), 100.);
    QCOMPARE(line.position(), QPointF(100, 0));

    /*
     * Blocks in cell 1,0 rules:
     *   Position      Content      Layout bounding rect
     *   15            "Cell 3"     0, 14.4 100x?
     */
    QTextBlock block3 = cell3.firstCursorPosition().block();
    QCOMPARE(block3.position(), 15);
    QVERIFY(block3.layout());
    QCOMPARE(block3.layout()->lineCount(), 1);
    line = block3.layout()->lineAt(0);
    QCOMPARE(line.width(), 100.);
    QCOMPARE(line.position().x(), 0.);
    QVERIFY(qAbs(line.position().y() - 14.4) < 0.156);

    /*
     * Blocks in cell 1,1 rules:
     *   Position      Content      Layout bounding rect
     *   22            "Cell 4"     100, 14.4 100x?
     */
    QTextBlock block4 = cell4.firstCursorPosition().block();
    QCOMPARE(block4.position(), 22);
    QVERIFY(block4.layout());
    QCOMPARE(block4.layout()->lineCount(), 1);
    line = block4.layout()->lineAt(0);
    QCOMPARE(line.width(), 100.);
    QCOMPARE(line.position().x(), 100.);
    QVERIFY(qAbs(line.position().y() - 14.4) < 0.156);

    /*
     * TODO: Insert/remove rows/columns.
     */

    cleanupTest();
}