📄 qtextdocumentlayout.cpp
字号:
int rspan = cell.rowSpan(); int cspan = cell.columnSpan(); if (rspan != 1) { int cr = cell.row(); if (cr != r) return; } if (cspan != 1) { int cc = cell.column(); if (cc != c) return; } if (td->border != 0) { const QBrush oldBrush = painter->brush(); const QPen oldPen = painter->pen(); const qreal border = td->border.toReal(); QRectF borderRect(cellRect.left() - border, cellRect.top() - border, cellRect.width() + border, cellRect.height() + border); // invert the border style for cells QTextFrameFormat::BorderStyle cellBorder = table->format().borderStyle(); switch (cellBorder) { case QTextFrameFormat::BorderStyle_Inset: cellBorder = QTextFrameFormat::BorderStyle_Outset; break; case QTextFrameFormat::BorderStyle_Outset: cellBorder = QTextFrameFormat::BorderStyle_Inset; break; case QTextFrameFormat::BorderStyle_Groove: cellBorder = QTextFrameFormat::BorderStyle_Ridge; break; case QTextFrameFormat::BorderStyle_Ridge: cellBorder = QTextFrameFormat::BorderStyle_Groove; break; default: break; } qreal topMargin = (td->effectiveTopMargin + td->cellSpacing + td->border).toReal(); qreal bottomMargin = (td->effectiveBottomMargin + td->cellSpacing + td->border).toReal(); const int headerRowCount = qMin(table->format().headerRowCount(), table->rows() - 1); if (r >= headerRowCount) topMargin += td->headerHeight.toReal(); drawBorder(painter, borderRect, topMargin, bottomMargin, border, table->format().borderBrush(), cellBorder); painter->setBrush(oldBrush); painter->setPen(oldPen); } { const QBrush bg = cell.format().background(); if (bg != Qt::NoBrush) fillBackground(painter, cellRect, bg); } const QFixed verticalOffset = td->cellVerticalOffsets.at(c + r * table->columns()); const QPointF cellPos = QPointF(cellRect.left() + td->cellPadding.toReal(), cellRect.top() + (td->cellPadding + verticalOffset).toReal()); QTextBlock repaintBlock; drawFlow(cellPos, painter, cell_context, cell.begin(), td->childFrameMap.values(r + c * table->rows()), &repaintBlock); if (repaintBlock.isValid()) { *cursorBlockNeedingRepaint = repaintBlock; *cursorBlockOffset = cellPos; }}void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextFrame::Iterator it, const QList<QTextFrame *> &floats, QTextBlock *cursorBlockNeedingRepaint) const{ Q_Q(const QTextDocumentLayout); const bool inRootFrame = (!it.atEnd() && it.parentFrame() && it.parentFrame()->parentFrame() == 0); QVector<QCheckPoint>::ConstIterator lastVisibleCheckPoint = checkPoints.end(); if (inRootFrame && context.clip.isValid()) { lastVisibleCheckPoint = qLowerBound(checkPoints.begin(), checkPoints.end(), QFixed::fromReal(context.clip.bottom())); } QTextBlock lastBlock; for (; !it.atEnd(); ++it) { QTextFrame *c = it.currentFrame(); if (inRootFrame && !checkPoints.isEmpty()) { int currentPosInDoc; if (c) currentPosInDoc = c->firstPosition(); else currentPosInDoc = it.currentBlock().position(); // if we're past what is already laid out then we're better off // not trying to draw things that may not be positioned correctly yet if (currentPosInDoc >= checkPoints.last().positionInFrame) break; if (lastVisibleCheckPoint != checkPoints.end() && context.clip.isValid() && currentPosInDoc >= lastVisibleCheckPoint->positionInFrame ) break; } if (c) drawFrame(offset, painter, context, c); else drawBlock(offset, painter, context, it.currentBlock()); // when entering a table and the previous block is empty // then layoutFlow 'hides' the block that just causes a // new line by positioning it /on/ the table border. as we // draw that block before the table itself the decoration // 'overpaints' the cursor and we need to paint it afterwards // again if (isEmptyBlockBeforeTable(lastBlock, it) && lastBlock.contains(context.cursorPosition) ) { *cursorBlockNeedingRepaint = lastBlock; } lastBlock = it.currentBlock(); } QTextDocument *document = q->document(); for (int i = 0; i < floats.count(); ++i) { QTextFrame *frame = floats.at(i); if (!isFrameFromInlineObject(frame) || frame->frameFormat().position() == QTextFrameFormat::InFlow) continue; const int pos = frame->firstPosition() - 1; QTextCharFormat format = const_cast<QTextDocumentLayout *>(q)->format(pos); QTextObjectInterface *handler = q->handlerForObject(format.objectType()); if (handler) { QRectF rect = frameBoundingRectInternal(frame); handler->drawObject(painter, rect, document, pos, format); } }}void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl) const{ Q_Q(const QTextDocumentLayout); const QTextLayout *tl = bl.layout(); QRectF r = tl->boundingRect(); r.translate(offset + tl->position()); if (context.clip.isValid() && (r.bottom() < context.clip.y() || r.top() > context.clip.bottom())) return;// LDEBUG << debug_indent << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect(); QTextBlockFormat blockFormat = bl.blockFormat(); QBrush bg = blockFormat.background(); if (bg != Qt::NoBrush) fillBackground(painter, r, bg); QVector<QTextLayout::FormatRange> selections; int blpos = bl.position(); int bllen = bl.length(); const QTextCharFormat *selFormat = 0; for (int i = 0; i < context.selections.size(); ++i) { const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i); const int selStart = range.cursor.selectionStart() - blpos; const int selEnd = range.cursor.selectionEnd() - blpos; if (selStart < bllen && selEnd > 0 && selEnd > selStart) { QTextLayout::FormatRange o; o.start = selStart; o.length = selEnd - selStart; o.format = range.format; selections.append(o); } else if (range.format.hasProperty(QTextFormat::FullWidthSelection) && bl.contains(range.cursor.position())) { // for full width selections we don't require an actual selection, just // a position to specify the line. that's more convenience in usage. QTextLayout::FormatRange o; QTextLine l = tl->lineForTextPosition(range.cursor.position() - blpos); o.start = l.textStart(); o.length = qMax(1, l.textLength()); o.format = range.format; selections.append(o); } if (selStart <= 0 && selEnd >= 1) selFormat = &range.format; } QTextObject *object = q->document()->objectForFormat(bl.blockFormat()); if (object && object->format().toListFormat().style() != QTextListFormat::ListStyleUndefined) drawListItem(offset, painter, context, bl, selFormat); QPen oldPen = painter->pen(); painter->setPen(context.palette.color(QPalette::Text)); tl->draw(painter, offset, selections, context.clip); if ((context.cursorPosition >= blpos && context.cursorPosition < blpos + bllen) || (context.cursorPosition < -1 && !tl->preeditAreaText().isEmpty())) { int cpos = context.cursorPosition; if (cpos < -1) cpos = tl->preeditAreaPosition() - (cpos + 2); else cpos -= blpos; tl->drawCursor(painter, offset, cpos, cursorWidth); } if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { const qreal width = blockFormat.lengthProperty(QTextFormat::BlockTrailingHorizontalRulerWidth).value(r.width()); painter->setPen(context.palette.color(QPalette::Dark)); qreal y = r.bottom(); if (bl.length() == 1) y = r.top() + r.height() / 2; const qreal middleX = r.left() + r.width() / 2; painter->drawLine(QLineF(middleX - width / 2, y, middleX + width / 2, y)); } painter->setPen(oldPen);}void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl, const QTextCharFormat *selectionFormat) const{ Q_Q(const QTextDocumentLayout); const QTextBlockFormat blockFormat = bl.blockFormat(); const QTextCharFormat charFormat = QTextCursor(bl).charFormat(); QFont font(charFormat.font()); if (q->paintDevice()) font = QFont(font, q->paintDevice()); const QFontMetrics fontMetrics(font); QTextObject * const object = q->document()->objectForFormat(blockFormat); const QTextListFormat lf = object->format().toListFormat(); int style = lf.style(); QString itemText; QSizeF size; if (blockFormat.hasProperty(QTextFormat::ListStyle)) style = QTextListFormat::Style(blockFormat.intProperty(QTextFormat::ListStyle)); QTextLayout *layout = bl.layout(); if (layout->lineCount() == 0) return; QTextLine firstLine = layout->lineAt(0); Q_ASSERT(firstLine.isValid()); QPointF pos = (offset + layout->position()).toPoint(); Qt::LayoutDirection dir = blockFormat.layoutDirection(); { QRectF textRect = firstLine.naturalTextRect(); pos += textRect.topLeft().toPoint(); if (dir == Qt::RightToLeft) pos.rx() += textRect.width(); } switch (style) { case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: case QTextListFormat::ListUpperAlpha: itemText = static_cast<QTextList *>(object)->itemText(bl); size.setWidth(fontMetrics.width(itemText)); size.setHeight(fontMetrics.height()); break; case QTextListFormat::ListSquare: case QTextListFormat::ListCircle: case QTextListFormat::ListDisc: size.setWidth(fontMetrics.lineSpacing() / 3); size.setHeight(size.width()); break; case QTextListFormat::ListStyleUndefined: return; default: return; } QRectF r(pos, size); qreal xoff = fontMetrics.width(QLatin1Char(' ')); if (dir == Qt::LeftToRight) xoff = -xoff - size.width(); r.translate( xoff, (fontMetrics.height() / 2 - size.height() / 2)); painter->save(); painter->setRenderHint(QPainter::Antialiasing); if (selectionFormat) { painter->setPen(QPen(selectionFormat->foreground(), 0)); painter->fillRect(r, selectionFormat->background()); } else { QBrush fg = charFormat.foreground(); if (fg == Qt::NoBrush) fg = context.palette.text(); painter->setPen(QPen(fg, 0)); } QBrush brush = context.palette.brush(QPalette::Text); switch (style) { case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: case QTextListFormat::ListUpperAlpha: { QTextLayout layout(itemText, font, q->paintDevice()); layout.setCacheEnabled(true); QTextOption option(Qt::AlignLeft | Qt::AlignAbsolute); option.setTextDirection(dir); layout.setTextOption(option); layout.beginLayout(); layout.createLine(); layout.endLayout(); layout.draw(painter, QPointF(r.left(), pos.y())); break; } case QTextListFormat::ListSquare: painter->fillRect(r, brush); break; case QTextListFormat::ListCircle: painter->drawEllipse(r); break; case QTextListFormat::ListDisc: painter->setBrush(brush); painter->setPen(Qt::NoPen); painter->drawEllipse(r); painter->setBrush(Qt::NoBrush); break; case QTextListFormat::ListStyleUndefined: break; default: break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -