Ejemplo n.º 1
0
void KTextDocumentLayout::Private::adjustSize()
{
    if (parent->resizeMethod() == KTextDocument::NoResize)
        return;

    if (parent->shapes().isEmpty())
        return;
    // Limit auto-resizing to the first shape only (there won't be more
    // with auto-resizing turned on, unless specifically set)
    KShape *shape = parent->shapes().first();

    // Determine the maximum width of all text lines
    qreal width = 0;
    for (QTextBlock block = parent->document()->begin(); block.isValid(); block = block.next()) {
        // The block layout's wrap mode must be QTextOption::NoWrap, thus the line count
        // of a valid block must be 1 (otherwise this resizing scheme wouldn't work)
        Q_ASSERT(block.layout()->lineCount() == 1);
        QTextLine line = block.layout()->lineAt(0);
        width = qMax(width, line.naturalTextWidth());
    }

    // Use position and height of last text line to calculate height
    QTextLine line = parent->document()->lastBlock().layout()->lineAt(0);
    qreal height = line.position().y() + line.height();

    shape->setSize(QSizeF(width, height));
}
Ejemplo n.º 2
0
QList<QGlyphRun> QTextFragment::glyphRuns(int pos, int len) const
{
    if (!p || !n)
        return QList<QGlyphRun>();

    int blockNode = p->blockMap().findNode(position());

    const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
    QTextLayout *layout = blockData->layout;

    int blockPosition = p->blockMap().position(blockNode);
    if (pos < 0)
        pos = position() - blockPosition;
    if (len < 0)
        len = length();
    if (len == 0)
        return QList<QGlyphRun>();

    QList<QGlyphRun> ret;
    for (int i=0; i<layout->lineCount(); ++i) {
        QTextLine textLine = layout->lineAt(i);
        ret += textLine.glyphRuns(pos, len);
    }

    return ret;
}
Ejemplo n.º 3
0
QPixmap QDeclarativeTextPrivate::wrappedTextImage(bool drawStyle)
{
    //do layout
    QSize size = cachedLayoutSize;

    int x = 0;
    for (int i = 0; i < layout.lineCount(); ++i) {
        QTextLine line = layout.lineAt(i);
        if (hAlign == QDeclarativeText::AlignLeft) {
            x = 0;
        } else if (hAlign == QDeclarativeText::AlignRight) {
            x = size.width() - (int)line.naturalTextWidth();
        } else if (hAlign == QDeclarativeText::AlignHCenter) {
            x = (size.width() - (int)line.naturalTextWidth()) / 2;
        }
        line.setPosition(QPoint(x, (int)line.y()));
    }

    //paint text
    QPixmap img(size);
    if (!size.isEmpty()) {
        img.fill(Qt::transparent);
        QPainter p(&img);
        drawWrappedText(&p, QPointF(0,0), drawStyle);
    }
    return img;
}
Ejemplo n.º 4
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();
    }
}
Ejemplo n.º 5
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());

}
Ejemplo n.º 6
0
 void setUnicodeText(const QString &text, const QFont &font, const QColor &color)
 {
     deleteContent();
     QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin);
     qreal line_width = raw_font.averageCharWidth() * text.size();
     QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext();
     QTextLayout layout(text,font);
     layout.beginLayout();
     QTextLine line = layout.createLine();
     line.setLineWidth(line_width);
     //Q_ASSERT(!layout.createLine().isValid());
     layout.endLayout();
     QList<QGlyphRun> glyphRuns = line.glyphRuns();
     qreal xpos = 0;
     for (int i = 0; i < glyphRuns.size(); i++) {
         QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr, false);
         node->setOwnerElement(m_owner);
         node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
         node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
         node->setGlyphs(QPointF(xpos, raw_font.ascent()), glyphRuns.at(i));
         node->setStyle(QQuickText::Normal);
         node->setColor(color);
         xpos += raw_font.averageCharWidth() * glyphRuns.at(i).positions().size();
         node->update();
         appendChildNode(node);
     }
 }
Ejemplo n.º 7
0
    void setContent(const ToolTipContent &data)
    {
        QString html;
        if (!data.mainText().isEmpty()) {
            html.append("<div><b>" + data.mainText() + "</b></div>");
        }
        html.append(data.subText());

        m_anchor.clear();
        m_document->clear();
        data.registerResources(m_document);
        if (!html.isEmpty()) {
            m_document->setHtml("<p>" + html + "</p>");
        }
        m_document->adjustSize();

        m_haloRects.clear();
        QTextLayout *layout = m_document->begin().layout();
        //layout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
        QTextLine line;
        for (int i = 0; i < layout->lineCount(); ++i) {
            line = layout->lineAt(i);

            // Add halo rect only when a non empty line is found
            if (line.naturalTextWidth()) {
                m_haloRects.append(line.naturalTextRect().translated(layout->position().toPoint()).toRect().translated(m_margin, m_margin));
            }
        }

        update();
    }
Ejemplo n.º 8
0
//virtual
void	PixButton::redoLabelTextLayout()
{
	//TODO: somewhat wasteful. If there is no label, should just exit early and leave a layout that will be left unrendered by paint()
	m_textLayoutObject.clearLayout();
	m_textLayoutObject.setText(m_label);
	m_textLayoutObject.setFont(m_textFont);
	QTextOption textOpts;
	textOpts.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
	textOpts.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
	m_textLayoutObject.setTextOption(textOpts);

	QFontMetrics textFontMetrics(m_textFont);
	int leading = textFontMetrics.leading();
	int rise = textFontMetrics.ascent();
	qreal height = 0;

	m_textLayoutObject.beginLayout();
	while (height < m_labelMaxGeom.height()) {
		QTextLine line = m_textLayoutObject.createLine();
		if (!line.isValid())
			break;
		line.setLineWidth(m_labelMaxGeom.width());
		if (m_textLayoutObject.lineCount() > 1)
		{
			height += leading;
		}
		line.setPosition(QPointF(0, height));
		height += line.height();
	}
	height = qMin((quint32)DimensionsGlobal::roundUp(height),(quint32)m_labelMaxGeom.height());
	height = DimensionsGlobal::roundDown(height) - (DimensionsGlobal::roundDown(height) % 2);	//force to an even #
	m_textLayoutObject.endLayout();
	//TODO: PIXEL-ALIGN
	m_labelGeom = DimensionsGlobal::realRectAroundRealPoint(QSizeF(m_textLayoutObject.boundingRect().width(),height)).toAlignedRect();
}
Ejemplo n.º 9
0
void PluginListDelegate::drawDisplay(QPainter* painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const
{
    QTextDocument textDocument;
    textDocument.setHtml(text);

    QTextLayout textLayout(textDocument.begin());
    textLayout.setFont(option.font);

    const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0) + 1;
    QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding

    textLayout.beginLayout();
    qreal height = 0;
    while (1) {
        QTextLine line = textLayout.createLine();
        if (!line.isValid()) {
            break;
        }

        line.setLineWidth(textRect.width());
        height += 3;
        line.setPosition(QPoint(0, height));
        height += line.height();
    }
    textLayout.endLayout();

    textLayout.draw(painter, QPointF(textRect.left(), textRect.top()));
}
Ejemplo n.º 10
0
void RowHeader::drawText(QPainter* painter, const QFont& font,
                         qreal ypos, qreal width, const QString& text) const
{
    register Sheet * const sheet = m_pCanvas->activeSheet();
    if (!sheet)
        return;

    const double scaleX = POINT_TO_INCH(double(KoDpi::dpiX()));
    const double scaleY = POINT_TO_INCH(double(KoDpi::dpiY()));

    // Qt scales the font already with the logical resolution. Do not do it twice!
    painter->save();
    painter->scale(1.0 / scaleX, 1.0 / scaleY);

    QTextLayout textLayout(text, font);
    textLayout.beginLayout();
    textLayout.setTextOption(QTextOption(Qt::AlignHCenter));
    forever {
        QTextLine line = textLayout.createLine();
        if (!line.isValid())
            break;
        line.setLineWidth(width * scaleX);
    }
    textLayout.endLayout();
    QPointF loc(0, ypos * scaleY);
    textLayout.draw(painter, loc);

    painter->restore();
}
Ejemplo n.º 11
0
int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
{
    QString string = qstring(run);
    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    return line.xToCursor(position);
}
Ejemplo n.º 12
0
int JobItem::descriptionHeight(const QStyleOptionViewItem & option)
{
    int textTotalWidth = 0;
    int lineWidth = option.rect.width() - 2 * m_itemPadding;
    QString description = m_job->description().simplified();
    QTextLayout descriptionLayout(description, m_descriptionFont, m_paintDevice);
    descriptionLayout.beginLayout();
    for (int i = 0; i < m_descriptionLineCount - 1; ++i)
    {
        QTextLine line = descriptionLayout.createLine();
        if (!line.isValid())
        {
            // There is no text left to be inserted into the layout.
            break;
        }
        line.setLineWidth(lineWidth);
        textTotalWidth += line.naturalTextWidth();
    }
    descriptionLayout.endLayout();

    // Add space for last visible line.
    textTotalWidth += lineWidth;

    m_descriptionText = m_descriptionFontMetrics.elidedText(description,
                                                            Qt::ElideRight,
                                                            textTotalWidth);
    m_descriptionRect =
        m_descriptionFontMetrics.boundingRect(0,
                                              0,
                                              option.rect.width() - 2 * m_itemPadding,
                                              0,
                                              descriptionFlags(),
                                              m_descriptionText);
    return m_descriptionRect.height();
}
Ejemplo n.º 13
0
void TestResultDelegate::recalculateTextLayout(const QModelIndex &index, const QString &output,
                                               const QFont &font, int width) const
{
    if (m_lastProcessedIndex == index && m_lastProcessedFont == font)
        return;

    const QFontMetrics fm(font);
    const int leading = fm.leading();
    const int fontHeight = fm.height();

    m_lastProcessedIndex = index;
    m_lastProcessedFont = font;
    m_lastCalculatedHeight = 0;
    m_lastCalculatedLayout.clearLayout();
    m_lastCalculatedLayout.setText(output);
    m_lastCalculatedLayout.setFont(font);
    QTextOption txtOption;
    txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    m_lastCalculatedLayout.setTextOption(txtOption);
    m_lastCalculatedLayout.beginLayout();
    while (true) {
        QTextLine line = m_lastCalculatedLayout.createLine();
        if (!line.isValid())
            break;
        line.setLineWidth(width);
        m_lastCalculatedHeight += leading;
        line.setPosition(QPoint(0, m_lastCalculatedHeight));
        m_lastCalculatedHeight += fontHeight;
    }
    m_lastCalculatedLayout.endLayout();
}
Ejemplo n.º 14
0
 bool addLine(QTextLine &line) {
     if (line.height() > 20)
         m_y += line.height();
     else
         m_y += 14.4;
     return false;
 }
Ejemplo n.º 15
0
  void UserIcon::init(){
    QString text = tr(user_->name().c_str());
    layout_ = new QTextLayout(text,
                              d_->users_scene()->font());
    QFontMetricsF fm(d_->users_scene()->font());
    layout_->beginLayout();
    QTextLine line = layout_->createLine();
    //line.setNumColumns(1);
    QSizeF text_size_ = fm.boundingRect(text).size();
    // TODO: Figure out what these numbers are all about, why width/4, height/4
    //line.setPosition(QPointF(s.width()/4.0,
                            // -s.height()/4.0));
    line.setPosition(QPointF());

    layout_->endLayout();
    layout_->setCacheEnabled(true);

    menu_ = new QMenu(tr(user_->name().c_str()));
    show_on_map_ = new QAction(tr("Show on map"), this);
    menu_->addAction(show_on_map_);
    connect(show_on_map_, SIGNAL(triggered()),
            this,
            SLOT(activateLastNode()));
    focus_on_ = new QAction(tr("Focus on"), this);
    menu_->addAction(focus_on_);
    connect(focus_on_, SIGNAL(triggered()),
            this,
            SLOT(focusOnLastNode()));

    updateDrawRect();
  }
Ejemplo n.º 16
0
void KCRowHeader::drawText(QPainter& painter, const QFont& font,
                         const QPointF& location, const QString& text) const
{
    register KCSheet * const sheet = m_pView->activeSheet();
    if (!sheet)
        return;

    const double scaleX = POINT_TO_INCH(double(KoDpi::dpiX()));
    const double scaleY = POINT_TO_INCH(double(KoDpi::dpiY()));

    // Qt scales the font already with the logical resolution. Do not do it twice!
    painter.save();
    painter.scale(1.0 / scaleX, 1.0 / scaleY);

    QTextLayout textLayout(text, font);
    textLayout.beginLayout();
    forever {
        QTextLine line = textLayout.createLine();
        if (!line.isValid())
            break;
        line.setLineWidth(width() * scaleX);
    }
    textLayout.endLayout();
    QPointF loc(location.x() * scaleX, location.y() * scaleY);
    textLayout.draw(&painter, loc);

    painter.restore();
}
Ejemplo n.º 17
0
void GroupedLineEdit::paintEvent(QPaintEvent *e)
{
	QTextLine line = document()->findBlock(0).layout()->lineAt(0);
	QPainter painter(viewport());

	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.fillRect(0, 0, viewport()->width(), viewport()->height(), palette().base());

	QVectorIterator<QColor> i(d->colors);
	i.toFront();
	foreach (const Private::Block &block, d->blocks) {
		qreal start_x = line.cursorToX(block.start, QTextLine::Leading);
		qreal end_x = line.cursorToX(block.end-1, QTextLine::Trailing);

		QPainterPath path;
		QRectF rectangle(
			start_x - 1.0 - double(horizontalScrollBar()->value()),
			1.0,
			end_x - start_x + 2.0,
			double(viewport()->height() - 2));
		if (!i.hasNext())
			i.toFront();
		path.addRoundedRect(rectangle, 5.0, 5.0);
		painter.setPen(i.peekNext());
		if (palette().color(QPalette::Text).lightnessF() <= 0.3)
			painter.setBrush(i.next().lighter());
		else if (palette().color(QPalette::Text).lightnessF() <= 0.6)
			painter.setBrush(i.next());
		else
			painter.setBrush(i.next().darker());
		painter.drawPath(path);
	}
	QPlainTextEdit::paintEvent(e);
}
Ejemplo n.º 18
0
int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const
{
    const QString string = fixSpacing(qstring(run));
    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    return line.xToCursor(position);
}
Ejemplo n.º 19
0
///Indique si on est à la dernière ligne
bool RzxTextEdit::atEnd() const
{
	QTextBlock block = textCursor().block();
	if(block.next().isValid()) return false;

	QTextLine line = currentTextLine();
	return line.isValid() && line.lineNumber() == block.layout()->lineCount() - 1;
}
Ejemplo n.º 20
0
///Indique si on est à la première ligne
bool RzxTextEdit::atBeginning() const
{
	QTextBlock block = textCursor().block();
	if(block.previous().isValid()) return false;

	QTextLine line = currentTextLine();
	return line.isValid() && !line.lineNumber();
}
Ejemplo n.º 21
0
void ChatItem::doLayout(QTextLayout *layout) const {
  layout->beginLayout();
  QTextLine line = layout->createLine();
  if(line.isValid()) {
    line.setLineWidth(width());
    line.setPosition(QPointF(0,0));
  }
  layout->endLayout();
}
Ejemplo n.º 22
0
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
{
    String sanitized = Font::normalizeSpaces(run.characters(), run.length());
    QString string = fromRawDataWithoutRef(sanitized);

    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    return line.xToCursor(position);
}
Ejemplo n.º 23
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));
}
Ejemplo n.º 24
0
 int cursorPosition() const {
     if (!m_currentBlock.isValid())
         return 0;
     int answer = m_currentBlock.position();
     if (m_currentBlock.layout()->lineCount()) {
         QTextLine tl = m_currentBlock.layout()->lineAt(m_currentBlock.layout()->lineCount() - 1);
         answer += tl.textStart() + tl.textLength();
     }
     return answer;
 }
Ejemplo n.º 25
0
void YTDelegate::layoutText(QTextLayout& textLayout, QString text, QSize constraint) const
{
    QTextOption textOption(Qt::AlignJustify);
    textLayout.setTextOption(textOption);
    textLayout.setText(text);
    textLayout.beginLayout();
    int lHeight = 0;
    while(true){
        QTextLine line = textLayout.createLine();
        if(!line.isValid())
            break;
        line.setLineWidth(constraint.width());
        line.setPosition(QPointF(0, lHeight));
        if(lHeight + line.height() > constraint.height())
        {
            QTextLine lastLine = textLayout.lineAt(textLayout.lineCount() - 2);
            QString lastString = text.mid(lastLine.textStart());
            QFontMetrics fm(textLayout.font());
            text.chop(lastString.length());
            text += fm.elidedText(lastString, Qt::ElideRight, constraint.width()-1);
            textLayout.endLayout();
            layoutText(textLayout, text, constraint);
            return;
        }
        lHeight += line.height();
        lHeight += line.leading();
    }
    textLayout.endLayout();
}
Ejemplo n.º 26
0
qreal TextDocumentLayout::blockWidth(const QTextBlock &block)
{
    QTextLayout *layout = block.layout();
    if (!layout->lineCount())
        return 0; // only for layouted blocks
    qreal blockWidth = 0;
    for (int i = 0; i < layout->lineCount(); ++i) {
        QTextLine line = layout->lineAt(i);
        blockWidth = qMax(line.naturalTextWidth() + 8, blockWidth);
    }
    return blockWidth;
}
Ejemplo n.º 27
0
void tst_QComplexText::bidiCursor_PDF()
{
    QString str = QString::fromUtf8("\342\200\252hello\342\200\254");
    QTextLayout layout(str);

    layout.beginLayout();
    QTextLine line = layout.createLine();
    layout.endLayout();

    int size = str.size();

    QVERIFY(line.cursorToX(size) == line.cursorToX(size - 1));
}
Ejemplo n.º 28
0
void LayerView::setDisplayedName(const QString& s)
{
    m_displayedName = s;

    m_textcache.setText(s);
    m_textcache.beginLayout();
    QTextLine line = m_textcache.createLine();
    line.setPosition(QPointF{0., 0.});

    m_textcache.endLayout();

    update();
}
Ejemplo n.º 29
0
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
{
    const QString string = fixSpacing(qstring(run));
    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);

    float x1 = line.cursorToX(from);
    float x2 = line.cursorToX(to);
    if (x2 < x1)
        qSwap(x1, x2);

    return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
}
Ejemplo n.º 30
0
int StyledLabel::posToCursor(const QPointF &pos)
{
    if (pos.y() < 0 || pos.y() > height())
        return -1;

    for (int l = _layout.lineCount() - 1; l >= 0; l--) {
        QTextLine line = _layout.lineAt(l);
        if (pos.y() >= line.y()) {
            return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
        }
    }
    return -1;
}