📄 qtextdocumentlayout.cpp
字号:
static bool operator<(const QCheckPoint &checkPoint, QFixed y){ return checkPoint.y < y;}static bool operator<(const QCheckPoint &checkPoint, int pos){ return checkPoint.positionInFrame < pos;}static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, QRectF gradientRect = QRectF()){ p->save(); if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) { if (!gradientRect.isNull()) { QTransform m; m.translate(gradientRect.left(), gradientRect.top()); m.scale(gradientRect.width(), gradientRect.height()); brush.setTransform(m); const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode); } } else { p->setBrushOrigin(rect.topLeft()); } p->fillRect(rect, brush); p->restore();}class QTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate{ Q_DECLARE_PUBLIC(QTextDocumentLayout)public: QTextDocumentLayoutPrivate(); QTextOption::WrapMode wordWrapMode;#ifdef LAYOUT_DEBUG mutable QString debug_indent;#endif int fixedColumnWidth; int cursorWidth; QSizeF lastReportedSize; mutable int currentLazyLayoutPosition; mutable int lazyLayoutStepSize; QBasicTimer layoutTimer; mutable QBasicTimer sizeChangedTimer; uint showLayoutProgress : 1; uint insideDocumentChange : 1; int lastPageCount; qreal idealWidth; bool contentHasAlignment; qreal indent(QTextBlock bl) const; void drawFrame(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextFrame *f) const; void drawFlow(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextFrame::Iterator it, const QList<QTextFrame *> &floats, QTextBlock *cursorBlockNeedingRepaint) const; void drawBlock(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl) const; void drawListItem(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl, const QTextCharFormat *selectionFormat) const; void drawTableCell(const QRectF &cellRect, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &cell_context, QTextTable *table, QTextTableData *td, int r, int c, QTextBlock *cursorBlockNeedingRepaint, QPointF *cursorBlockOffset) const; void drawBorder(QPainter *painter, const QRectF &rect, qreal topMargin, qreal bottomMargin, qreal border, const QBrush &brush, QTextFrameFormat::BorderStyle style) const; void drawFrameDecoration(QPainter *painter, QTextFrame *frame, QTextFrameData *fd, const QRectF &clip, const QRectF &rect) const; enum HitPoint { PointBefore, PointAfter, PointInside, PointExact }; HitPoint hitTest(QTextFrame *frame, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const; HitPoint hitTest(QTextFrame::Iterator it, HitPoint hit, const QFixedPoint &p, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const; HitPoint hitTest(QTextTable *table, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const; HitPoint hitTest(QTextBlock bl, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const; QLayoutStruct layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width, int layoutFrom, int layoutTo, QTextTableData *tableData, QFixed absoluteTableY, bool withPageBreaks); void setCellPosition(QTextTable *t, const QTextTableCell &cell, const QPointF &pos); QRectF layoutTable(QTextTable *t, int layoutFrom, int layoutTo, QFixed parentY); void positionFloat(QTextFrame *frame, QTextLine *currentLine = 0); // calls the next one QRectF layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed parentY = 0); QRectF layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed frameWidth, QFixed frameHeight, QFixed parentY = 0); 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, QFixed width = 0); void pageBreakInsideTable(QTextTable *table, QLayoutStruct *layoutStruct); void floatMargins(QFixed y, const QLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const; QFixed findY(QFixed yFrom, const QLayoutStruct *layoutStruct, QFixed requiredWidth) const; QVector<QCheckPoint> checkPoints; QTextFrame::Iterator frameIteratorForYPosition(QFixed y) const; QTextFrame::Iterator frameIteratorForTextPosition(int position) const; void ensureLayouted(QFixed y) const; void ensureLayoutedByPosition(int position) const; inline void ensureLayoutFinished() const { ensureLayoutedByPosition(INT_MAX); } void layoutStep() const; QRectF frameBoundingRectInternal(QTextFrame *frame) const; qreal scaleToDevice(qreal value) const; QFixed scaleToDevice(QFixed value) const;};QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() : fixedColumnWidth(-1), cursorWidth(1), currentLazyLayoutPosition(-1), lazyLayoutStepSize(1000), lastPageCount(-1){ showLayoutProgress = true; insideDocumentChange = false; idealWidth = 0; contentHasAlignment = false;}QTextFrame::Iterator QTextDocumentLayoutPrivate::frameIteratorForYPosition(QFixed 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 frameIteratorForTextPosition(position);}QTextFrame::Iterator QTextDocumentLayoutPrivate::frameIteratorForTextPosition(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 QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const{ Q_Q(const QTextDocumentLayout); QTextFrameData *fd = data(frame); // ######### if (fd->layoutDirty) return PointAfter; Q_ASSERT(!fd->layoutDirty); Q_ASSERT(!fd->sizeDirty); const QFixedPoint relativePoint(point.x - fd->position.x, point.y - fd->position.y); 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 (isFrameFromInlineObject(frame)) { *position = frame->firstPosition() - 1; return PointExact; } if (QTextTable *table = qobject_cast<QTextTable *>(frame)) { const int rows = table->rows(); const int columns = table->columns(); QTextTableData *td = static_cast<QTextTableData *>(data(table)); if (!td->childFrameMap.isEmpty()) { for (int r = 0; r < rows; ++r) { for (int c = 0; c < columns; ++c) { QTextTableCell cell = table->cellAt(r, c); if (cell.row() != r || cell.column() != c) continue; QRectF cellRect = td->cellRect(cell); const QFixedPoint cellPos = QFixedPoint::fromPointF(cellRect.topLeft()); const QFixedPoint pointInCell = relativePoint - cellPos; const QList<QTextFrame *> childFrames = td->childFrameMap.values(r + c * rows); for (int i = 0; i < childFrames.size(); ++i) { QTextFrame *child = childFrames.at(i); if (isFrameFromInlineObject(child) && child->frameFormat().position() != QTextFrameFormat::InFlow && hitTest(child, pointInCell, position, l, accuracy) == PointExact) { return PointExact; } } } } } return hitTest(table, relativePoint, position, l, accuracy); } const QList<QTextFrame *> childFrames = frame->childFrames(); for (int i = 0; i < childFrames.size(); ++i) { QTextFrame *child = childFrames.at(i); if (isFrameFromInlineObject(child) && child->frameFormat().position() != QTextFrameFormat::InFlow && hitTest(child, relativePoint, position, l, accuracy) == PointExact) { return PointExact; } } QTextFrame::Iterator it = frame->begin(); if (frame == rootFrame) { it = frameIteratorForYPosition(relativePoint.y); Q_ASSERT(it.parentFrame() == frame); } if (it.currentFrame()) *position = it.currentFrame()->firstPosition(); else *position = it.currentBlock().position(); return hitTest(it, PointBefore, relativePoint, position, l, accuracy);}QTextDocumentLayoutPrivate::HitPointQTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const QFixedPoint &p, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const{ INC_INDENT; for (; !it.atEnd(); ++it) { QTextFrame *c = it.currentFrame(); HitPoint hp; int pos = -1; if (c) { hp = hitTest(c, p, &pos, l, accuracy); } else { hp = hitTest(it.currentBlock(), p, &pos, l, accuracy); } 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 QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const{ QTextTableData *td = static_cast<QTextTableData *>(data(table)); QVector<QFixed>::ConstIterator rowIt = qLowerBound(td->rowPositions.constBegin(), td->rowPositions.constEnd(), point.y); if (rowIt == td->rowPositions.constEnd()) { rowIt = td->rowPositions.constEnd() - 1; } else if (rowIt != td->rowPositions.constBegin()) { --rowIt; } QVector<QFixed>::ConstIterator colIt = qLowerBound(td->columnPositions.constBegin(), td->columnPositions.constEnd(), point.x); if (colIt == td->columnPositions.constEnd()) { colIt = td->columnPositions.constEnd() - 1; } else if (colIt != td->columnPositions.constBegin()) { --colIt; } QTextTableCell cell = table->cellAt(rowIt - td->rowPositions.constBegin(), colIt - td->columnPositions.constBegin()); if (!cell.isValid()) return PointBefore;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -