📄 qtextdocumentlayout.cpp
字号:
td->minimumWidth += td->minWidths.at(i) + td->border + cellSpacing + td->border; } td->minimumWidth += margin - td->border; td->maximumWidth = td->columnPositions.at(0); for (int i = 0; i < columns; ++i) if (td->maxWidths.at(i) != INT_MAX) td->maximumWidth += td->maxWidths.at(i) + td->border + cellSpacing + td->border; td->maximumWidth += margin - td->border; td->rowPositionsBeforePageBreak = td->rowPositions; td->updateSize(); td->sizeDirty = false; return QRectF(); // invalid rect -> update everything}void QTextDocumentLayoutPrivate::positionFloat(QTextFrame *frame, QTextLine *currentLine){ QTextFrameData *fd = data(frame); QTextFrame *parent = frame->parentFrame(); Q_ASSERT(parent); QTextFrameData *pd = data(parent); Q_ASSERT(pd && pd->currentLayoutStruct); if (!pd->floats.contains(frame)) pd->floats.append(frame); fd->layoutDirty = true; Q_ASSERT(!fd->sizeDirty);// qDebug() << "positionFloat:" << frame << "width=" << fd->size.width(); qreal y = pd->currentLayoutStruct->y; if (currentLine) { qreal left, right; floatMargins(y, pd->currentLayoutStruct, &left, &right);// qDebug() << "have line: right=" << right << "left=" << left << "textWidth=" << currentLine->textWidth(); if (right - left < currentLine->naturalTextWidth() + fd->size.width()) { pd->currentLayoutStruct->pendingFloats.append(frame);// qDebug() << " adding to pending list"; return; } } if (!parent->parentFrame() /* float in root frame */ && y + fd->size.height() > pd->currentLayoutStruct->pageBottom) { y = pd->currentLayoutStruct->pageBottom; } y = findY(y, pd->currentLayoutStruct, fd->size.width()); qreal left, right; floatMargins(y, pd->currentLayoutStruct, &left, &right); if (fd->flow_position == QTextFrameFormat::FloatLeft) fd->position = QPointF(left, y); else fd->position = QPointF(right - fd->size.width(), y);// qDebug()<< "float positioned at " << fd->position; fd->layoutDirty = false;}QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo){ LDEBUG << "layoutFrame (pre)"; Q_ASSERT(data(f)->sizeDirty);// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame()); QTextFrameFormat fformat = f->frameFormat(); QTextFrame *parent = f->parentFrame(); const QTextFrameData *pd = parent ? data(parent) : 0; const qreal maximumWidth = pd ? pd->contentsWidth : q_func()->document()->pageSize().width(); const qreal width = fformat.width().value(maximumWidth); QTextLength height = fformat.height(); qreal h = height.value(pd ? pd->contentsHeight : -1); return layoutFrame(f, layoutFrom, layoutTo, width, h);}QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, qreal frameWidth, qreal frameHeight){ LDEBUG << "layoutFrame from=" << layoutFrom << "to=" << layoutTo; Q_Q(QTextDocumentLayout); Q_ASSERT(data(f)->sizeDirty);// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame()); QTextFrameData *fd = data(f); { QTextFrameFormat fformat = f->frameFormat(); // set sizes of this frame from the format fd->margin = fformat.margin(); fd->border = fformat.border(); fd->padding = fformat.padding(); fd->contentsWidth = frameWidth - 2*(fd->margin + fd->border + fd->padding); if (frameHeight != -1) { fd->contentsHeight = frameHeight - 2*(fd->margin + fd->border + fd->padding); } else { fd->contentsHeight = frameHeight; } fd->flow_position = fformat.position(); } int startPos = f->firstPosition(); int endPos = f->lastPosition(); if (startPos > endPos) { // inline image QTextCharFormat format = q->format(startPos - 1); QTextObjectInterface *iface = q->handlerForObject(format.objectType()); if (iface) fd->size = iface->intrinsicSize(q->document(), startPos - 1, format).toSize(); fd->sizeDirty = false; return QRectF(); } if (QTextTable *table = qobject_cast<QTextTable *>(f)) { return layoutTable(table, layoutFrom, layoutTo); } // needed for child frames with a minimum width that is // more than what we can offer qreal newContentsWidth = fd->contentsWidth; // layout child frames QList<QTextFrame *> children = f->childFrames(); for (int i = 0; i < children.size(); ++i) { QTextFrame *c = children.at(i); QTextFrameData *cd = data(c); if (cd->sizeDirty) { layoutFrame(c, layoutFrom, layoutTo); } newContentsWidth = qMax(newContentsWidth, cd->size.width()); } qreal margin = fd->margin + fd->border; QLayoutStruct layoutStruct; layoutStruct.frame = f; layoutStruct.x_left = margin + fd->padding; layoutStruct.x_right = margin + fd->contentsWidth - fd->padding; layoutStruct.y = margin + fd->padding; layoutStruct.contentsWidth = 0; layoutStruct.minimumWidth = 0; layoutStruct.maximumWidth = INT_MAX; layoutStruct.fullLayout = fd->contentsWidth != newContentsWidth; layoutStruct.updateRect = QRectF(QPointF(0, 0), QSizeF(INT_MAX, INT_MAX)); LDEBUG << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right << "fullLayout" << layoutStruct.fullLayout; fd->contentsWidth = newContentsWidth; if (!f->parentFrame()) { layoutStruct.pageHeight = q->document()->pageSize().height(); layoutStruct.pageBottom = layoutStruct.pageHeight - fd->margin; layoutStruct.pageMargin = fd->margin; } QTextFrame::Iterator it = f->begin(); layoutFlow(it, &layoutStruct, layoutFrom, layoutTo); fd->contentsWidth = qMax(fd->contentsWidth, layoutStruct.contentsWidth); fd->minimumWidth = layoutStruct.minimumWidth; fd->maximumWidth = layoutStruct.maximumWidth; qreal height = fd->contentsHeight == -1 ? layoutStruct.y + margin + fd->padding : fd->contentsHeight + 2*margin; fd->size = QSizeF(fd->contentsWidth + 2*margin, height); fd->sizeDirty = false; return layoutStruct.updateRect;}void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QLayoutStruct *layoutStruct, int layoutFrom, int layoutTo){ Q_Q(QTextDocumentLayout); LDEBUG << "layoutFlow from=" << layoutFrom << "to=" << layoutTo; QTextFrameData *fd = data(layoutStruct->frame); fd->currentLayoutStruct = layoutStruct; QTextFrame::Iterator previousIt; const bool inRootFrame = (it.parentFrame() == q->document()->rootFrame()); if (inRootFrame) { bool redoCheckPoints = layoutStruct->fullLayout || checkPoints.isEmpty(); if (!redoCheckPoints) { QVector<QCheckPoint>::Iterator checkPoint = qLowerBound(checkPoints.begin(), checkPoints.end(), layoutFrom); if (checkPoint != checkPoints.end()) { if (checkPoint != checkPoints.begin()) --checkPoint; layoutStruct->y = checkPoint->y; layoutStruct->minimumWidth = checkPoint->minimumWidth; layoutStruct->maximumWidth = checkPoint->maximumWidth; layoutStruct->contentsWidth = checkPoint->contentsWidth; if (layoutStruct->pageHeight > 0.0) { int page = int(layoutStruct->y / layoutStruct->pageHeight); layoutStruct->pageBottom = (page + 1) * layoutStruct->pageHeight - layoutStruct->pageMargin; } it = iteratorForTextPosition(checkPoint->positionInFrame); checkPoints.resize(checkPoint - checkPoints.begin() + 1); if (checkPoint != checkPoints.begin()) { previousIt = it; --previousIt; } } else { redoCheckPoints = true; } } if (redoCheckPoints) { checkPoints.clear(); QCheckPoint cp; cp.y = layoutStruct->y; cp.positionInFrame = 0; cp.minimumWidth = layoutStruct->minimumWidth; cp.maximumWidth = layoutStruct->maximumWidth; cp.contentsWidth = layoutStruct->contentsWidth; checkPoints.append(cp); } } while (!it.atEnd()) { QTextFrame *c = it.currentFrame(); if (inRootFrame) { int docPos; if (it.currentFrame()) docPos = it.currentFrame()->firstPosition(); else docPos = it.currentBlock().position(); if (qAbs(layoutStruct->y - checkPoints.last().y) > 2000) { qreal left, right; floatMargins(layoutStruct->y, layoutStruct, &left, &right); if (left == layoutStruct->x_left && right == layoutStruct->x_right) { QCheckPoint p; p.y = layoutStruct->y; p.positionInFrame = docPos; p.minimumWidth = layoutStruct->minimumWidth; p.maximumWidth = layoutStruct->maximumWidth; p.contentsWidth = layoutStruct->contentsWidth; checkPoints.append(p); if (currentLazyLayoutPosition != -1 && docPos > currentLazyLayoutPosition + lazyLayoutStepSize) break; if (layoutTo != -1 && docPos > layoutTo) break; } } } if (c) { // position child frame QTextFrameData *cd = data(c); Q_ASSERT(!cd->sizeDirty); if (cd->flow_position == QTextFrameFormat::InFlow) { qreal left, right; floatMargins(layoutStruct->y, layoutStruct, &left, &right); left = qMax(left, layoutStruct->x_left); right = qMin(right, layoutStruct->x_right); if (right - left < cd->size.width()) { layoutStruct->y = findY(layoutStruct->y, layoutStruct, cd->size.width()); floatMargins(layoutStruct->y, layoutStruct, &left, &right); } QPointF pos(left, layoutStruct->y); Qt::Alignment align = Qt::AlignLeft; QTextTable *table = qobject_cast<QTextTable *>(c); if (table) align = table->format().alignment() & Qt::AlignHorizontal_Mask; // align only if there is space for alignment if (right - left > cd->size.width()) { if (align == Qt::AlignRight) pos.rx() += layoutStruct->x_right - cd->size.width(); else if (align == Qt::AlignHCenter) pos.rx() += (layoutStruct->x_right - cd->size.width()) / 2; } cd->position = pos; layoutStruct->y += cd->size.height(); cd->layoutDirty = false; if (table) { QTextTableData *td = static_cast<QTextTableData *>(data(table)); // if the table was previously broken across a page boundary // (due to lazy layouting) then we need to reset the row positions // and the table height (from the row positions) and call // pageBreakInsideTable again. if (!td->rowPageBreaks.isEmpty()) { td->rowPageBreaks.clear(); td->rowPositions = td->rowPositionsBeforePageBreak; td->updateSize(); } } if (inRootFrame && cd->position.y() + cd->size.height() > layoutStruct->pageBottom ) { if (table && cd->size.height() > layoutStruct->pageHeight / 2) { pageBreakInsideTable(table, layoutStruct); } else { layoutStruct->newPage(); cd->position.setY(layoutStruct->y); layoutStruct->y += cd->size.height(); } } } else { positionFloat(c); } previousIt = it; ++it; } else { QTextFrame::Iterator lastIt; if (!previousIt.atEnd()) lastIt = previousIt; previousIt = it; QTextBlock block = it.currentBlock(); ++it; const qreal origY = layoutStruct->y; // layout and position child block layoutBlock(block, layoutStruct, layoutFrom, layoutTo, lastIt.currentBlock()); // if the block right before a table is empty 'hide' it by // positioning it into the table border if (isEmptyBlockBeforeTable(block, it)) { layoutStruct->y = origY; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -