void KPrAttributeHeight::initCache(KPrAnimationCache *animationCache, int step, KPrShapeAnimation * shapeAnimation, qreal startValue, qreal endValue) { qreal v1 = 0.0, v2 = 0.0, tx = 0.0, ty = 0.0; KoShape * shape = shapeAnimation->shape(); KoTextBlockData * textBlockData = shapeAnimation->textBlockData(); if (textBlockData) { if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) { QTextDocument *textDocument = textShapeData->document(); for (int i = 0; i < textDocument->blockCount(); i++) { QTextBlock textBlock = textDocument->findBlockByNumber(i); if (textBlock.userData() == textBlockData) { QTextLayout *layout = textBlock.layout(); v1 = startValue * animationCache->pageSize().height() / layout->boundingRect().height(); v2 = endValue * animationCache->pageSize().height() / layout->boundingRect().height(); tx = layout->minimumWidth() * animationCache->zoom() / 2; ty = layout->boundingRect().height() * animationCache->zoom() / 2; } } } } else { v1 = startValue * animationCache->pageSize().height() / shape->size().height(); v2 = endValue * animationCache->pageSize().height() / shape->size().height(); tx = shape->size().width() * animationCache->zoom() / 2; ty = shape->size().height() * animationCache->zoom() / 2; } animationCache->init(step, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v1).translate(-tx, -ty)); animationCache->init(step + 1, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v2).translate(-tx, -ty)); }
void KPrAttributeHeight::updateCache(KPrAnimationCache *cache, KPrShapeAnimation *shapeAnimation, qreal value) { qreal tx = 0.0, ty = 0.0; KoShape * shape = shapeAnimation->shape(); KoTextBlockData * textBlockData = shapeAnimation->textBlockData(); QTransform transform; if (textBlockData) { if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) { QTextDocument *textDocument = textShapeData->document(); for (int i = 0; i < textDocument->blockCount(); i++) { QTextBlock textBlock = textDocument->findBlockByNumber(i); if (textBlock.userData() == textBlockData) { QTextLayout *layout = textBlock.layout(); value = value * cache->pageSize().height() / layout->boundingRect().height(); tx = layout->minimumWidth() * cache->zoom() / 2; ty = layout->boundingRect().height() * cache->zoom() / 2; } } } } else { value = value * cache->pageSize().height() / shape->size().height(); tx = shape->size().width() * cache->zoom() / 2; ty = shape->size().height() * cache->zoom() / 2; } transform.translate(tx, ty).scale(1, value).translate(-tx, -ty); cache->update(shape, shapeAnimation->textBlockData(), "transform", transform); }
void DevLineNumber::paintEvent(QPaintEvent *e) { const QPixmap pm[] ={ QPixmap(":/break.png"), QPixmap(":/error.png") }; int n = 1, contentsY = editor->verticalScrollBar()->value(); qreal pageBottom = contentsY + editor->viewport()->height(); const QFontMetrics fm( editor->document()->defaultFont() ); QPainter p(this); for (QTextBlock block = editor->document()->begin(); block.isValid(); block = block.next(), ++n ) { QTextLayout *layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if (position.y() + boundingRect.height() < contentsY) continue; if (position.y() > pageBottom) break; int posY = qRound(position.y()); BlockData *dat = BlockData::data(block); const QString txt = QString::number(n); p.drawText( 0, posY - contentsY, width(), fm.lineSpacing(), Qt::AlignRight | Qt::AlignVCenter, txt); if ( !dat ) continue; int x = 0; if ( dat->s & BlockData::BreakPoint ) p.drawPixmap( 15*(x++), posY - contentsY +(fm.lineSpacing() - (*pm).height())/2, (*pm).width(), (*pm).height(), *pm); if ( dat->s & BlockData::Error ) p.drawPixmap( 15*(x++), posY - contentsY +(fm.lineSpacing() - pm[1].height())/2, pm[1].width(), pm[1].height(), pm[1]); } }
int KTextDocumentLayout::hitTestIterated(QTextFrame::iterator begin, QTextFrame::iterator end, const QPointF &point, Qt::HitTestAccuracy accuracy) const { int position = -1; QTextFrame::iterator it = begin; for (it = begin; it != end; ++it) { QTextBlock block = it.currentBlock(); QTextTable *table = qobject_cast<QTextTable*>(it.currentFrame()); QTextFrame *subFrame = it.currentFrame(); if (table) { QTextTableCell cell = m_state->hitTestTable(table, point); if (cell.isValid()) { position = hitTestIterated(cell.begin(), cell.end(), point, accuracy); if (position == -1) position = cell.lastPosition(); return position; } continue; } else if (subFrame) { position = hitTestIterated(subFrame->begin(), subFrame->end(), point, accuracy); if (position != -1) return position; continue; } else { if (!block.isValid()) continue; } // kDebug(32500) <<"hitTest[" << point.x() <<"," << point.y() <<"]"; QTextLayout *layout = block.layout(); if (point.y() > layout->boundingRect().bottom()) { // just skip this block. position = block.position() + block.length() - 1; continue; } for (int i = 0; i < layout->lineCount(); i++) { QTextLine line = layout->lineAt(i); // kDebug(32500) <<" + line[" << line.textStart() <<"]:" << line.y() <<"-" << line.height(); if (point.y() > line.y() + line.height()) { position = line.textStart() + line.textLength(); continue; } if (accuracy == Qt::ExactHit && point.y() < line.y()) // between lines return -1; if (accuracy == Qt::ExactHit && // left or right of line (point.x() < line.x() || point.x() > line.x() + line.width())) return -1; if (point.x() > line.width() && layout->textOption().textDirection() == Qt::RightToLeft) { // totally right of RTL text means the position is the start of the text. return block.position() + line.textStart(); } return block.position() + line.xToCursor(point.x()); } } return -1; }
bool XMLTextEdit::event( QEvent *event ) { if (event->type()==QEvent::Paint) { QPainter p(this); p.fillRect(0, 0, 50, height(), QColor("#636363")); QFont workfont(font()); QPen pen(QColor("#ffffff"),1); p.setPen(pen); p.setFont (workfont); int contentsY = verticalScrollBar()->value(); qreal pageBottom = contentsY+viewport()->height(); int m_lineNumber(1); const QFontMetrics fm=fontMetrics(); const int ascent = fontMetrics().ascent() +1; for (QTextBlock block=document()->begin(); block.isValid(); block=block.next(), m_lineNumber++) { QTextLayout *layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if ( position.y() +boundingRect.height() < contentsY ) { continue; } if ( position.y() > pageBottom ) { break; } const QString txt = QString::number(m_lineNumber); p.drawText(50-fm.width(txt)-2, qRound(position.y())-contentsY+ascent, txt); } p.setPen(QPen(Qt::NoPen)); } else if ( event->type() == QEvent::KeyPress ) { QKeyEvent *ke = static_cast<QKeyEvent *>(event); if ((ke->modifiers() & Qt::ControlModifier) && ke->key() == Qt::Key_Minus) { QTextEdit::zoomOut(); return true; } if ((ke->modifiers() & Qt::ControlModifier) && ke->key() == Qt::Key_Plus) { QTextEdit::zoomIn(); return true; } } return QTextEdit::event(event); }
QRectF TextDocumentLayout::blockBoundingRect(const QTextBlock &block) const { if (!block.isValid()) { return QRectF(); } QTextLayout *tl = block.layout(); if (!tl->lineCount()) const_cast<TextDocumentLayout*>(this)->layoutBlock(block); QRectF br; if (block.isVisible()) { br = QRectF(QPointF(0, 0), tl->boundingRect().bottomRight()); if (tl->lineCount() == 1) br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth())); qreal margin = document()->documentMargin(); br.adjust(0, 0, margin, 0); if (!block.next().isValid()) br.adjust(0, 0, 0, margin); } return br; }
void LineNumbers::paintEvent( QPaintEvent* ) { int contentsY = m_textEdit->verticalScrollBar()->value(); qreal pageBottom = contentsY + m_textEdit->viewport()->height(); int m_lineNumber = 1; const QFontMetrics fm = fontMetrics(); const int ascent = fontMetrics().ascent() +1; QPainter p( this ); for ( QTextBlock block = m_textEdit->document()->begin(); block.isValid(); block = block.next(), m_lineNumber++ ) { QTextLayout* layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if ( position.y() +boundingRect.height() < contentsY ) continue; if ( position.y() > pageBottom ) break; const QString txt = QString::number( m_lineNumber ); if( m_lineNumber == m_executedLine ) { int centreV = qRound( position.y() ) -contentsY + 8; p.setBrush( Qt::blue ); float x = width()-1; const QPointF points[7] = { QPointF(x, centreV), QPointF(x-9, centreV-8), QPointF(x-9, centreV-4), QPointF(x-15, centreV-4), QPointF(x-15, centreV+4), QPointF(x-9, centreV+4), QPointF(x-9, centreV+8), }; p.drawPolygon(points, 7); } else p.drawText( width() -fm.width( txt ) - 2, qRound( position.y() ) -contentsY +ascent, txt ); } p.end(); }
void LineNumberWidget::paintEvent(QPaintEvent *){ int contentsY = editor->verticalScrollBar()->value(); qreal pageBottom = contentsY + editor->viewport()->height(); int lineNumber = 1; const QFontMetrics fm = fontMetrics(); const int ascent = fontMetrics().ascent() + 1; // height = ascent + descent + 1 QPainter p(this); for (QTextBlock block = editor->document()->begin();block.isValid();block = block.next(), ++lineNumber) { QTextLayout *layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if (position.y() + boundingRect.height() < contentsY) continue; if (position.y() > pageBottom) break; const QString txt = QString::number(lineNumber); p.drawText(width() - fm.width(txt), qRound(position.y()) - contentsY + ascent, txt); } }
void TextLineNumbers::paintEvent( QPaintEvent* ) { int contentsY = m_textEdit->verticalScrollBar()->value(); qreal pageBottom = contentsY + m_textEdit->viewport()->height(); int m_lineNumber = 1; const QFontMetrics fm = fontMetrics(); const int ascent = fontMetrics().ascent() +1; QPainter p( this ); for ( QTextBlock block = m_textEdit->document()->begin(); block.isValid(); block = block.next(), m_lineNumber++ ) { QTextLayout* layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if ( position.y() +boundingRect.height() < contentsY ) continue; if ( position.y() > pageBottom ) break; const QString txt = QString::number( m_lineNumber - 1 ); p.drawText( width() -fm.width( txt ) - 2, qRound( position.y() ) -contentsY +ascent, txt ); // -fm.width( "0" ) is an ampty place/indent } p.end(); }
void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p) { bool preferRichText = textFormat == Qt::RichText || (textFormat == Qt::AutoText && Qt::mightBeRichText(text)); if (!preferRichText) { QTextLayout textLayout; textLayout.setText(text); textLayout.setFont(font); textLayout.setTextOption(textOption); qreal leading = QFontMetricsF(font).leading(); qreal height = -leading; textLayout.beginLayout(); while (1) { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; if (textWidth >= 0.0) line.setLineWidth(textWidth); height += leading; line.setPosition(QPointF(0.0, height)); height += line.height(); } textLayout.endLayout(); actualSize = textLayout.boundingRect().size(); textLayout.draw(p, topLeftPosition); } else { QTextDocument document; #ifndef QT_NO_CSSPARSER QColor color = p->pen().color(); document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }") .arg(QString::number(color.red(), 16), 2, QLatin1Char('0')) .arg(QString::number(color.green(), 16), 2, QLatin1Char('0')) .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0'))); #endif document.setDefaultFont(font); document.setDocumentMargin(0.0); #ifndef QT_NO_TEXTHTMLPARSER document.setHtml(text); #else document.setPlainText(text); #endif if (textWidth >= 0.0) document.setTextWidth(textWidth); else document.adjustSize(); document.setDefaultTextOption(textOption); p->save(); p->translate(topLeftPosition); QAbstractTextDocumentLayout::PaintContext ctx; ctx.palette.setColor(QPalette::Text, p->pen().color()); document.documentLayout()->draw(p, ctx); p->restore(); if (textWidth >= 0.0) document.adjustSize(); // Find optimal size actualSize = document.size(); } }
void ScCodeEditor::blinkCode( const QTextCursor & c ) { if( !c.document() || !c.hasSelection() ) return; Settings::Manager *settings = Main::settings(); QTextCharFormat evalCodeTextFormat = settings->getThemeVal("evaluatedCode"); QTextDocument *doc = c.document(); int startPos = c.selectionStart(); int endPos = c.selectionEnd(); QTextBlock startBlock = doc->findBlock(startPos); QTextBlock endBlock = doc->findBlock(endPos); startPos -= startBlock.position(); endPos -= endBlock.position(); // Get the bounds of visible blocks within the cursor's selection: QTextBlock block = firstVisibleBlock(); int idx = block.blockNumber(); int sidx = startBlock.blockNumber(); QTextBlock firstBlock, lastBlock; firstBlock = lastBlock = block; QRectF geom = blockBoundingGeometry(block).translated(contentOffset()); qreal top = geom.top(); qreal bottom = top; qreal width=0; while(block.isValid() && bottom < viewport()->rect().height()) { if(block.isVisible()) { QTextLayout *l = block.layout(); QRectF r = l->boundingRect(); bottom += r.height(); if(idx < sidx) { // Block not within the selection. Will skip it. top = bottom; } else { // Block within the selection. width = qMax(width, l->maximumWidth() + r.left()); } } if(block == endBlock) break; block = block.next(); ++idx; if(top == bottom) firstBlock = block; } lastBlock = block; if(bottom == top) { //qDebug("no visible block."); return; } // Construct a pixmap to render the code on: QPixmap pix( QSize(qCeil(width), qCeil(bottom - top)) ); pix.fill(QColor(0,0,0,0)); // Render the visible blocks: QPainter painter(&pix); QVector<QTextLayout::FormatRange> selections; block = firstBlock; int y=0; while( block.isValid() ) { if (block.isVisible()) { QRectF blockRect = block.layout()->boundingRect(); // Use extra char formatting to hide code outside of selection // and modify the appearance of selected code: QTextLayout::FormatRange range; selections.clear(); int start = 0; if(block == startBlock) { range.start = 0; range.length = startPos; range.format.setForeground(QColor(0,0,0,0)); range.format.setBackground(Qt::NoBrush); selections.append(range); start = startPos; } range.start = start; range.length = (block == endBlock ? endPos : block.length() - 1) - range.start; range.format = evalCodeTextFormat; selections.append(range); if(block == endBlock) { range.start = range.start + range.length; range.length = block.length() - 1 - range.start; range.format.setForeground(QColor(0,0,0,0)); range.format.setBackground(Qt::NoBrush); selections.append(range); } block.layout()->draw(&painter, QPointF(0,y), selections); y += blockRect.height(); } if(block == lastBlock) break; block = block.next(); } // Create an overlay item to display the pixmap, and animate it: CodeFragmentOverlay *item = new CodeFragmentOverlay(); item->setPixmap(pix); item->setPos(geom.left(), top); mOverlay->addItem(item); QPropertyAnimation *anim = new QPropertyAnimation(item, "opacity", item); anim->setDuration(mBlinkDuration); anim->setStartValue(1.0); anim->setEndValue(0.0); anim->setEasingCurve( QEasingCurve::InCubic ); anim->start(); connect(anim, SIGNAL(finished()), item, SLOT(deleteLater())); }