📄 qtextdocumentlayout.cpp
字号:
QLayoutStruct layoutCell(QTextTable *t, const QTextTableCell &cell, qreal width, int layoutFrom, int layoutTo); void setCellPosition(QTextTable *t, const QTextTableCell &cell, const QPointF &pos); QRectF layoutTable(QTextTable *t, int layoutFrom, int layoutTo); void positionFloat(QTextFrame *frame, QTextLine *currentLine = 0); // calls the next one QRectF layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo); QRectF layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, qreal frameWidth, qreal frameHeight); void layoutBlock(const QTextBlock &bl, QLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlock &previousBlock); void layoutFlow(QTextFrame::Iterator it, QLayoutStruct *layoutStruct, int layoutFrom, int layoutTo); void pageBreakInsideTable(QTextTable *table, QLayoutStruct *layoutStruct); void floatMargins(qreal y, const QLayoutStruct *layoutStruct, qreal *left, qreal *right) const; qreal findY(qreal yFrom, const QLayoutStruct *layoutStruct, qreal requiredWidth) const; QVector<QCheckPoint> checkPoints; QTextFrame::Iterator iteratorForYPosition(qreal y) const; QTextFrame::Iterator iteratorForTextPosition(int position) const; void ensureLayouted(qreal y) const; void ensureLayoutedByPosition(int position) const; inline void ensureLayoutFinished() const { ensureLayoutedByPosition(INT_MAX); } void layoutStep() const;};QTextFrame::Iterator QTextDocumentLayoutPrivate::iteratorForYPosition(qreal y) const{ Q_Q(const QTextDocumentLayout); const QTextDocumentPrivate *doc = q->document()->docHandle(); QTextFrame *rootFrame = doc->rootFrame(); if (checkPoints.isEmpty() || y < 0 || y > data(rootFrame)->size.height()) return rootFrame->begin(); QVector<QCheckPoint>::ConstIterator checkPoint = qLowerBound(checkPoints.begin(), checkPoints.end(), y); if (checkPoint == checkPoints.end()) return rootFrame->begin(); if (checkPoint != checkPoints.begin()) --checkPoint; const int position = rootFrame->firstPosition() + checkPoint->positionInFrame; return iteratorForTextPosition(position);}QTextFrame::Iterator QTextDocumentLayoutPrivate::iteratorForTextPosition(int position) const{ Q_Q(const QTextDocumentLayout); const QTextDocumentPrivate *doc = q->document()->docHandle(); QTextFrame *rootFrame = doc->rootFrame(); const QTextDocumentPrivate::BlockMap &map = doc->blockMap(); const int begin = map.findNode(rootFrame->firstPosition()); const int end = map.findNode(rootFrame->lastPosition()+1); const int block = map.findNode(position); const int blockPos = map.position(block); QTextFrame::iterator it(rootFrame, block, begin, end); QTextFrame *containingFrame = doc->frameAt(blockPos); if (containingFrame != rootFrame) { while (containingFrame->parentFrame() != rootFrame) { containingFrame = containingFrame->parentFrame(); Q_ASSERT(containingFrame); } it.cf = containingFrame; it.cb = 0; } return it;}QTextDocumentLayoutPrivate::HitPointQTextDocumentLayoutPrivate::hitTest(QTextFrame *frame, const QPointF &point, int *position, QTextLayout **l) const{ Q_Q(const QTextDocumentLayout); QTextFrameData *fd = data(frame); // ######### if (fd->layoutDirty) return PointAfter; Q_ASSERT(!fd->layoutDirty); Q_ASSERT(!fd->sizeDirty); const QPointF relativePoint = point - fd->position; QTextFrame *rootFrame = q->document()->rootFrame();// LDEBUG << "checking frame" << frame->firstPosition() << "point=" << point// << "position" << fd->position << "size" << fd->size; if (frame != rootFrame) { if (relativePoint.y() < 0 || relativePoint.x() < 0) { *position = frame->firstPosition() - 1;// LDEBUG << "before pos=" << *position; return PointBefore; } else if (relativePoint.y() > fd->size.height() || relativePoint.x() > fd->size.width()) { *position = frame->lastPosition() + 1;// LDEBUG << "after pos=" << *position; return PointAfter; } } if (QTextTable *table = qobject_cast<QTextTable *>(frame)) return hitTest(table, relativePoint, position, l); HitPoint hit = PointInside; QTextFrame::Iterator it = frame->begin(); if (frame == rootFrame) { it = iteratorForYPosition(relativePoint.y()); Q_ASSERT(it.parentFrame() == frame); if (it.currentFrame()) *position = it.currentFrame()->firstPosition(); else *position = it.currentBlock().position(); hit = PointBefore; } return hitTest(it, hit, relativePoint, position, l);}QTextDocumentLayoutPrivate::HitPointQTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const QPointF &p, int *position, QTextLayout **l) const{ INC_INDENT; for (; !it.atEnd(); ++it) { QTextFrame *c = it.currentFrame(); HitPoint hp; int pos = -1; if (c) { hp = hitTest(c, p, &pos, l); } else { hp = hitTest(it.currentBlock(), p, &pos, l); } if (hp >= PointInside) { if (isEmptyBlockBeforeTable(it)) continue; hit = hp; *position = pos; break; } if (hp == PointBefore && pos < *position) { *position = pos; hit = hp; } else if (hp == PointAfter && pos > *position) { *position = pos; hit = hp; } } DEC_INDENT;// LDEBUG << "inside=" << hit << " pos=" << *position; return hit;}QTextDocumentLayoutPrivate::HitPointQTextDocumentLayoutPrivate::hitTest(QTextTable *table, const QPointF &point, int *position, QTextLayout **l) const{ QTextTableData *td = static_cast<QTextTableData *>(data(table)); QVector<qreal>::ConstIterator rowIt = qLowerBound(td->rowPositions.begin(), td->rowPositions.end(), point.y()); if (rowIt == td->rowPositions.end()) { rowIt = td->rowPositions.end() - 1; } else if (rowIt != td->rowPositions.begin()) { --rowIt; } QVector<qreal>::ConstIterator colIt = qLowerBound(td->columnPositions.begin(), td->columnPositions.end(), point.x()); if (colIt == td->columnPositions.end()) { colIt = td->columnPositions.end() - 1; } else if (colIt != td->columnPositions.begin()) { --colIt; } QTextTableCell cell = table->cellAt(rowIt - td->rowPositions.begin(), colIt - td->columnPositions.begin()); if (!cell.isValid()) return PointBefore; *position = cell.firstPosition(); HitPoint hp = hitTest(cell.begin(), PointInside, point - td->cellPosition(cell), position, l); if (hp == PointExact) return hp; if (hp == PointAfter) *position = cell.lastPosition(); return PointInside;}QTextDocumentLayoutPrivate::HitPointQTextDocumentLayoutPrivate::hitTest(QTextBlock bl, const QPointF &point, int *position, QTextLayout **l) const{ QTextLayout *tl = bl.layout(); QRectF textrect = tl->boundingRect(); textrect.translate(tl->position());// LDEBUG << " checking block" << bl.position() << "point=" << point// << " tlrect" << textrect; *position = bl.position(); if (point.y() < textrect.top()) {// LDEBUG << " before pos=" << *position; return PointBefore; } else if (point.y() > textrect.bottom()) { *position += bl.length();// LDEBUG << " after pos=" << *position; return PointAfter; } QPointF pos = point - textrect.topLeft(); // ### rtl? HitPoint hit = PointInside; *l = tl; int off = 0; for (int i = 0; i < tl->lineCount(); ++i) { QTextLine line = tl->lineAt(i); const QRectF lr = line.naturalTextRect(); if (lr.top() > pos.y()) { off = qMin(off, line.textStart()); } else if (lr.bottom() <= pos.y()) { off = qMax(off, line.textStart() + line.textLength()); } else { if (lr.left() > pos.x()) { off = line.textStart(); } else if (lr.right() < pos.x()) { off = line.textStart() + line.textLength(); } else { hit = PointExact; off = line.xToCursor(pos.x()); } break; } } *position += off;// LDEBUG << " inside=" << hit << " pos=" << *position; return hit;}// ### could be moved to QTextBlockqreal QTextDocumentLayoutPrivate::indent(QTextBlock bl) const{ Q_Q(const QTextDocumentLayout); QTextBlockFormat blockFormat = bl.blockFormat(); qreal indent = blockFormat.indent(); QTextObject *object = q->document()->objectForFormat(blockFormat); if (object) indent += object->format().toListFormat().indent(); qreal scale = 1; if (q->paintDevice()) { extern int qt_defaultDpi(); scale = qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()); } return indent * TextIndentValue * scale;}static void drawFrameDecoration(QPainter *painter, QTextFrame *frame, QTextFrameData *fd, const QRectF &clip, const QRectF &rect){ if (fd->border) { painter->save(); painter->setBrush(Qt::lightGray); painter->setPen(Qt::NoPen); const qreal margin = fd->margin + fd->border; const qreal w = rect.width() - 2*margin; const qreal h = rect.height() - 2*margin; // left painter->drawRect(QRectF(rect.left() + fd->margin, rect.top() + fd->margin, fd->border, h + 2 * fd->border)); // top painter->drawRect(QRectF(rect.left() + fd->margin + fd->border, rect.top() + fd->margin, w + fd->border, fd->border)); painter->setBrush(Qt::darkGray); // right painter->drawRect(QRectF(rect.left() + fd->margin + fd->border + w, rect.top() + fd->margin + fd->border, fd->border, h)); // bottom painter->drawRect(QRectF(rect.left() + fd->margin + fd->border, rect.top() + fd->margin + fd->border + h, w + fd->border, fd->border)); painter->restore(); } const QBrush bg = frame->frameFormat().background(); if (bg != Qt::NoBrush) { QRectF bgRect = rect; const qreal margin = fd->margin + fd->border; bgRect.adjust(margin, margin, -margin, -margin); if (!frame->parentFrame()) bgRect = clip; painter->fillRect(bgRect, bg); }}void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextFrame *frame) const{ Q_Q(const QTextDocumentLayout); QTextFrameData *fd = data(frame); // ####### if (fd->layoutDirty) return; Q_ASSERT(!fd->sizeDirty); Q_ASSERT(!fd->layoutDirty); const QPointF off = offset + fd->position; if (context.clip.isValid() && (off.y() > context.clip.bottom() || off.y() + fd->size.height() < context.clip.top() || off.x() > context.clip.right() || off.x() + fd->size.width() < context.clip.left())) return;// LDEBUG << debug_indent << "drawFrame" << frame->firstPosition() << "--" << frame->lastPosition() << "at" << offset;// INC_INDENT; // if the cursor is /on/ a table border we may need to repaint it // afterwards, as we usually draw the decoration first QTextBlock cursorBlockNeedingRepaint; QPointF offsetOfRepaintedCursorBlock = off; QTextTable *table = qobject_cast<QTextTable *>(frame); const QRectF frameRect(off, fd->size); if (table) { const int rows = table->rows(); const int columns = table->columns(); QTextTableData *td = static_cast<QTextTableData *>(data(table)); QVarLengthArray<int> selectedTableCells(context.selections.size() * 4); for (int i = 0; i < context.selections.size(); ++i) { const QAbstractTextDocumentLayout::Selection &s = context.selections.at(i); int row_start = -1, col_start = -1, num_rows = -1, num_cols = -1; if (s.cursor.currentTable() == table) s.cursor.selectedTableCells(&row_start, &num_rows, &col_start, &num_cols); selectedTableCells[i * 4] = row_start; selectedTableCells[i * 4 + 1] = col_start; selectedTableCells[i * 4 + 2] = num_rows;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -