#include <qdebug.h>
#include <qmutex.h>
#include "qbitmap.h"
#include "qimage.h"
#include "qpaintdevice.h"
#include "qpaintengine.h"
#include "qpainter.h"
#include "qpainter_p.h"
#include "qpainterpath.h"
#include "qpicture.h"
#include "qpixmapcache.h"
#include "qpolygon.h"
#include "qtextlayout.h"
#include "qwidget.h"
#include "qapplication.h"
#include "qstyle.h"
#include "qthread.h"
#include "qvarlengtharray.h"
#include <private/qfontengine_p.h>
#include <private/qpaintengine_p.h>
#include <private/qpainterpath_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
#include <math.h>
Include dependency graph for qpainter.cpp:

Go to the source code of this file.
Classes | |
| struct | QPaintDeviceRedirection |
Defines | |
| #define | QGradient_StretchToDevice 0x10000000 |
| #define | QPaintEngine_OpaqueBackground 0x40000000 |
Typedefs | |
| typedef QList< QPaintDeviceRedirection > | QPaintDeviceRedirectionList |
Functions | |
| QPixmap | qt_pixmapForBrush (int style, bool invert) |
| void | qt_format_text (const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString &str, QRectF *brect, int tabstops, int *tabarray, int tabarraylen, QPainter *painter) |
| static bool | check_gradient (const QBrush &brush) |
| static bool | is_brush_transparent (const QBrush &brush) |
| static bool | is_pen_transparent (const QPen &pen) |
| static uint | line_emulation (uint emulation) |
| void | qt_painter_tread_test () |
| static QPainterPath | generateWavyPath (qreal minWidth, QPaintDevice *device) |
| static void | drawTextItemDecoration (QPainter *painter, const QPointF &pos, const QTextItemInt &ti) |
| void | qt_painter_removePaintDevice (QPaintDevice *dev) |
| void | qt_format_text (const QFont &fnt, const QRectF &_r, int tf, const QString &str, QRectF *brect, int tabstops, int *ta, int tabarraylen, QPainter *painter) |
| #define QGradient_StretchToDevice 0x10000000 |
Definition at line 54 of file qpainter.cpp.
Referenced by QPainterPrivate::draw_helper(), line_emulation(), and QPainterPrivate::updateEmulationSpecifier().
| #define QPaintEngine_OpaqueBackground 0x40000000 |
Definition at line 55 of file qpainter.cpp.
Referenced by QPainterPrivate::draw_helper(), line_emulation(), and QPainterPrivate::updateEmulationSpecifier().
Definition at line 5729 of file qpainter.cpp.
| static bool check_gradient | ( | const QBrush & | brush | ) | [inline, static] |
Definition at line 70 of file qpainter.cpp.
References Qt::ConicalGradientPattern, QGradient::coordinateMode(), QBrush::gradient(), Qt::LinearGradientPattern, Qt::RadialGradientPattern, QGradient::StretchToDeviceMode, and QBrush::style().
Referenced by QPainterPrivate::drawStretchToDevice(), and QPainterPrivate::updateEmulationSpecifier().
00071 { 00072 switch (brush.style()) { 00073 case Qt::LinearGradientPattern: 00074 case Qt::RadialGradientPattern: 00075 case Qt::ConicalGradientPattern: 00076 if (brush.gradient()->coordinateMode() == QGradient::StretchToDeviceMode) 00077 return true; 00078 default: 00079 ; 00080 } 00081 return false; 00082 }
Here is the call graph for this function:

| static void drawTextItemDecoration | ( | QPainter * | painter, | |
| const QPointF & | pos, | |||
| const QTextItemInt & | ti | |||
| ) | [static] |
Definition at line 4621 of file qpainter.cpp.
References QPainter::Antialiasing, QFontEngine::ascent(), QPainter::brush(), ceil, QPen::color(), QPainter::device(), QPainter::drawLine(), QPainter::drawPath(), QTextItemInt::flags, QTextItemInt::fontEngine, generateWavyPath(), int, QColor::isValid(), QFontEngine::lineThickness(), Qt::NoBrush, QTextCharFormat::NoUnderline, QTextItem::Overline, QPainter::pen(), QPainter::restore(), QPainter::save(), QPainter::setBrush(), QPen::setColor(), QPainter::setPen(), QPainter::setRenderHint(), QPen::setStyle(), QPen::setWidthF(), QStyle::SH_SpellCheckUnderlineStyle, Qt::SolidLine, QTextCharFormat::SpellCheckUnderline, QTextItem::StrikeOut, QApplication::style(), styleHint(), QFixed::toReal(), QLineF::translate(), QPainter::translate(), QTextItemInt::underlineColor, QFontEngine::underlinePosition(), QTextItemInt::underlineStyle, QTextCharFormat::WaveUnderline, QTextItemInt::width, QPointF::x(), and QPointF::y().
Referenced by QPainter::drawTextItem().
04622 { 04623 QFontEngine *fe = ti.fontEngine; 04624 04625 const QPen oldPen = painter->pen(); 04626 const QBrush oldBrush = painter->brush(); 04627 painter->setBrush(Qt::NoBrush); 04628 QPen pen = oldPen; 04629 pen.setStyle(Qt::SolidLine); 04630 pen.setWidthF(fe->lineThickness().toReal()); 04631 04632 QLineF line(pos.x(), pos.y(), pos.x() + ti.width.toReal(), pos.y()); 04633 // deliberately ceil the offset to avoid the underline coming too close to 04634 // the text above it. 04635 const int underlinePos = int(ceil(pos.y()) + ceil(fe->underlinePosition().toReal())); 04636 04637 QTextCharFormat::UnderlineStyle underlineStyle = ti.underlineStyle; 04638 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { 04639 underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle)); 04640 } 04641 04642 if (underlineStyle == QTextCharFormat::WaveUnderline) { 04643 painter->save(); 04644 painter->setRenderHint(QPainter::Antialiasing); 04645 painter->translate(pos.x(), underlinePos); 04646 04647 if (ti.underlineColor.isValid()) 04648 painter->setPen(ti.underlineColor); 04649 04650 painter->drawPath(generateWavyPath(ti.width.toReal(), painter->device())); 04651 painter->restore(); 04652 } else if (underlineStyle != QTextCharFormat::NoUnderline) { 04653 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos); 04654 04655 if (ti.underlineColor.isValid()) 04656 pen.setColor(ti.underlineColor); 04657 04658 pen.setStyle((Qt::PenStyle)(underlineStyle)); 04659 painter->setPen(pen); 04660 painter->drawLine(underLine); 04661 } 04662 04663 pen.setStyle(Qt::SolidLine); 04664 pen.setColor(oldPen.color()); 04665 04666 if (ti.flags & QTextItem::StrikeOut) { 04667 QLineF strikeOutLine = line; 04668 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.); 04669 painter->drawLine(strikeOutLine); 04670 } 04671 04672 if (ti.flags & QTextItem::Overline) { 04673 QLineF overLine = line; 04674 overLine.translate(0., - fe->ascent().toReal()); 04675 painter->drawLine(overLine); 04676 } 04677 04678 painter->setPen(oldPen); 04679 painter->setBrush(oldBrush); 04680 }
Here is the call graph for this function:

| static QPainterPath generateWavyPath | ( | qreal | minWidth, | |
| QPaintDevice * | device | |||
| ) | [static] |
Definition at line 4595 of file qpainter.cpp.
References i, QPaintDevice::logicalDpiY(), path, and qt_defaultDpi().
Referenced by drawTextItemDecoration().
04596 { 04597 extern int qt_defaultDpi(); 04598 QPainterPath path; 04599 04600 bool up = true; 04601 const int radius = 2 * device->logicalDpiY() / qt_defaultDpi(); 04602 qreal xs, ys; 04603 int i = 0; 04604 do { 04605 int endAngle = up ? -180 : 180; 04606 04607 xs = i*(2*radius); 04608 ys = 0; 04609 04610 // we need to move to the start of the new arc to not have the path 04611 // be implicitly connected for us 04612 path.arcMoveTo(xs, ys, 2*radius, 2*radius, 0); 04613 path.arcTo(xs, ys, 2*radius, 2*radius, 0, endAngle); 04614 up = !up; 04615 ++i; 04616 } while (xs + radius < minWidth); 04617 04618 return path; 04619 }
Here is the call graph for this function:

| static bool is_brush_transparent | ( | const QBrush & | brush | ) | [inline, static] |
Definition at line 84 of file qpainter.cpp.
References Qt::Dense1Pattern, Qt::DiagCrossPattern, QPixmap::isQBitmap(), s, QBrush::style(), QBrush::texture(), and Qt::TexturePattern.
Referenced by is_pen_transparent(), and QPainterPrivate::updateEmulationSpecifier().
00084 { 00085 Qt::BrushStyle s = brush.style(); 00086 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern) 00087 || (s == Qt::TexturePattern && brush.texture().isQBitmap())); 00088 }
Here is the call graph for this function:

| static bool is_pen_transparent | ( | const QPen & | pen | ) | [inline, static] |
Definition at line 90 of file qpainter.cpp.
References QPen::brush(), is_brush_transparent(), Qt::SolidLine, and QPen::style().
Referenced by QPainterPrivate::updateEmulationSpecifier().
00090 { 00091 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush()); 00092 }
Here is the call graph for this function:

| static uint line_emulation | ( | uint | emulation | ) | [inline, static] |
Definition at line 97 of file qpainter.cpp.
References QPaintEngine::AlphaBlend, QPaintEngine::Antialiasing, QPaintEngine::BrushStroke, QPaintEngine::ConstantOpacity, QPaintEngine::PrimitiveTransform, QGradient_StretchToDevice, and QPaintEngine_OpaqueBackground.
Referenced by QPainter::drawLines(), and QPainter::drawPolyline().
00098 { 00099 return emulation & (QPaintEngine::PrimitiveTransform 00100 | QPaintEngine::AlphaBlend 00101 | QPaintEngine::Antialiasing 00102 | QPaintEngine::BrushStroke 00103 | QPaintEngine::ConstantOpacity 00104 | QGradient_StretchToDevice 00105 | QPaintEngine_OpaqueBackground); 00106 }
| void qt_format_text | ( | const QFont & | fnt, | |
| const QRectF & | _r, | |||
| int | tf, | |||
| const QString & | str, | |||
| QRectF * | brect, | |||
| int | tabstops, | |||
| int * | ta, | |||
| int | tabarraylen, | |||
| QPainter * | painter | |||
| ) |
Definition at line 5822 of file qpainter.cpp.
References qt_format_text().
05826 { 05827 qt_format_text(fnt, _r, 05828 tf, 0, str, brect, 05829 tabstops, ta, tabarraylen, 05830 painter); 05831 }
Here is the call graph for this function:

| void qt_format_text | ( | const QFont & | font, | |
| const QRectF & | _r, | |||
| int | tf, | |||
| const QTextOption * | option, | |||
| const QString & | str, | |||
| QRectF * | brect, | |||
| int | tabstops, | |||
| int * | tabarray, | |||
| int | tabarraylen, | |||
| QPainter * | painter | |||
| ) |
Definition at line 5832 of file qpainter.cpp.
References Qt::AlignBottom, Qt::AlignHCenter, Qt::AlignLeft, Qt::AlignRight, Qt::AlignVCenter, QTextLayout::beginLayout(), QRectF::contains(), QTextLayout::createLine(), QString::data(), QTextLayout::endLayout(), QTextLayout::engine(), QRectF::height(), height, QFontMetricsF::height(), i, QTextEngine::ignoreBidi, Qt::IntersectClip, QString::isEmpty(), l, layout_direction, QPainter::layoutDirection(), QFontMetricsF::leading(), Qt::LeftToRight, QString::length(), QTextLayout::lineAt(), QTextLayout::lineCount(), QChar::LineSeparator, QTextEngine::option, qMax(), qRound(), QString::resize(), QPainter::restore(), Qt::RightToLeft, QPainter::save(), QTextLayout::setCacheEnabled(), QPainter::setClipRect(), QTextOption::setTextDirection(), QTextOption::setWrapMode(), QTextOption::textDirection(), Qt::TextDontClip, Qt::TextDontPrint, Qt::TextExpandTabs, Qt::TextHideMnemonic, Qt::TextIncludeTrailingSpaces, Qt::TextShowMnemonic, Qt::TextSingleLine, Qt::TextWordWrap, Qt::TextWrapAnywhere, QTextEngine::underlinePositions, QString::unicode(), QStyle::visualAlignment(), QRectF::width(), QFontMetricsF::width(), width, QTextOption::WrapAnywhere, QRectF::x(), and QRectF::y().
05836 { 05837 // we need to copy r here to protect against the case (&r == brect). 05838 QRectF r(_r); 05839 05840 bool dontclip = (tf & Qt::TextDontClip); 05841 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere); 05842 bool singleline = (tf & Qt::TextSingleLine); 05843 bool showmnemonic = (tf & Qt::TextShowMnemonic); 05844 bool hidemnmemonic = (tf & Qt::TextHideMnemonic); 05845 05846 Qt::LayoutDirection layout_direction; 05847 if(option) 05848 layout_direction = option->textDirection(); 05849 else if (painter) 05850 layout_direction = painter->layoutDirection(); 05851 else 05852 layout_direction = Qt::LeftToRight; 05853 05854 tf = QStyle::visualAlignment(layout_direction, QFlag(tf)); 05855 05856 bool isRightToLeft = layout_direction == Qt::RightToLeft; 05857 bool expandtabs = ((tf & Qt::TextExpandTabs) && 05858 (((tf & Qt::AlignLeft) && !isRightToLeft) || 05859 ((tf & Qt::AlignRight) && isRightToLeft))); 05860 05861 if (!painter) 05862 tf |= Qt::TextDontPrint; 05863 05864 int maxUnderlines = 0; 05865 int numUnderlines = 0; 05866 int underlinePositionStack[32]; 05867 int *underlinePositions = underlinePositionStack; 05868 05869 QFontMetricsF fm(fnt); 05870 05871 QString text = str; 05872 // compatible behaviour to the old implementation. Replace 05873 // tabs by spaces 05874 QChar *chr = text.data(); 05875 const QChar *end = chr + str.length(); 05876 bool has_tab = false; 05877 while (chr != end) { 05878 if (*chr == QLatin1Char('\r') || (singleline && *chr == QLatin1Char('\n'))) { 05879 *chr = QLatin1Char(' '); 05880 } else if (*chr == QLatin1Char('\n')) { 05881 *chr = QChar::LineSeparator; 05882 } else if (*chr == QLatin1Char('&')) { 05883 ++maxUnderlines; 05884 } else if (*chr == QLatin1Char('\t')) { 05885 has_tab = true; 05886 } 05887 ++chr; 05888 } 05889 if (has_tab) { 05890 if (!expandtabs) { 05891 chr = text.data(); 05892 while (chr != end) { 05893 if (*chr == QLatin1Char('\t')) 05894 *chr = QLatin1Char(' '); 05895 ++chr; 05896 } 05897 } else if (!tabarraylen && !tabstops) { 05898 tabstops = qRound(fm.width(QLatin1Char('x'))*8); 05899 } 05900 } 05901 05902 if (hidemnmemonic || showmnemonic) { 05903 if (maxUnderlines > 32) 05904 underlinePositions = new int[maxUnderlines]; 05905 QChar *cout = text.data(); 05906 QChar *cin = cout; 05907 int l = str.length(); 05908 while (l) { 05909 if (*cin == QLatin1Char('&')) { 05910 ++cin; 05911 --l; 05912 if (!l) 05913 break; 05914 if (*cin != QLatin1Char('&') && !hidemnmemonic) 05915 underlinePositions[numUnderlines++] = cout - text.unicode(); 05916 } 05917 *cout = *cin; 05918 ++cout; 05919 ++cin; 05920 --l; 05921 } 05922 int newlen = cout - text.unicode(); 05923 if (newlen != text.length()) 05924 text.resize(newlen); 05925 } 05926 05927 // no need to do extra work for underlines if we don't paint 05928 if (tf & Qt::TextDontPrint) 05929 numUnderlines = 0; 05930 05931 underlinePositions[numUnderlines] = -1; 05932 qreal height = 0; 05933 qreal width = 0; 05934 05935 QStackTextEngine engine(text, fnt); 05936 engine.option.setTextDirection(layout_direction); 05937 if (tf & Qt::TextWrapAnywhere) 05938 engine.option.setWrapMode(QTextOption::WrapAnywhere); 05939 QTextLayout textLayout(&engine); 05940 textLayout.setCacheEnabled(true); 05941 textLayout.engine()->underlinePositions = underlinePositions; 05942 05943 if (text.isEmpty()) { 05944 height = fm.height(); 05945 width = 0; 05946 tf |= Qt::TextDontPrint; 05947 } else { 05948 qreal lineWidth = wordwrap ? qMax<qreal>(0, r.width()) : 0x01000000; 05949 if(!wordwrap) 05950 tf |= Qt::TextIncludeTrailingSpaces; 05951 textLayout.engine()->ignoreBidi = (tf & Qt::TextDontPrint); 05952 textLayout.beginLayout(); 05953 05954 qreal leading = fm.leading(); 05955 height = -leading; 05956 05957 while (1) { 05958 QTextLine l = textLayout.createLine(); 05959 if (!l.isValid()) 05960 break; 05961 05962 l.setLineWidth(lineWidth); 05963 height += leading; 05964 l.setPosition(QPointF(0., height)); 05965 height += l.height(); 05966 width = qMax(width, l.naturalTextWidth()); 05967 if (!brect && height >= r.height()) 05968 break; 05969 } 05970 textLayout.endLayout(); 05971 } 05972 05973 qreal yoff = 0; 05974 qreal xoff = 0; 05975 if (tf & Qt::AlignBottom) 05976 yoff = r.height() - height; 05977 else if (tf & Qt::AlignVCenter) 05978 yoff = (r.height() - height)/2; 05979 if (tf & Qt::AlignRight) 05980 xoff = r.width() - width; 05981 else if (tf & Qt::AlignHCenter) 05982 xoff = (r.width() - width)/2; 05983 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height); 05984 if (brect) 05985 *brect = bounds; 05986 05987 if (!(tf & Qt::TextDontPrint)) { 05988 bool restore = false; 05989 if (!dontclip && !r.contains(bounds)) { 05990 restore = true; 05991 painter->save(); 05992 painter->setClipRect(r, Qt::IntersectClip); 05993 } 05994 05995 for (int i = 0; i < textLayout.lineCount(); i++) { 05996 QTextLine line = textLayout.lineAt(i); 05997 05998 if (tf & Qt::AlignRight) 05999 xoff = r.width() - line.naturalTextWidth(); 06000 else if (tf & Qt::AlignHCenter) 06001 xoff = (r.width() - line.naturalTextWidth())/2; 06002 06003 line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); 06004 } 06005 06006 if (restore) { 06007 painter->restore(); 06008 } 06009 } 06010 06011 if (underlinePositions != underlinePositionStack) 06012 delete [] underlinePositions; 06013 }
Here is the call graph for this function:

| void qt_painter_removePaintDevice | ( | QPaintDevice * | dev | ) |
Definition at line 5809 of file qpainter.cpp.
References i.
Referenced by QPaintDevice::~QPaintDevice().
05810 { 05811 QMutexLocker locker(globalRedirectionsMutex()); 05812 if(QPaintDeviceRedirectionList *redirections = globalRedirections()) { 05813 for (int i = 0; i < redirections->size(); ) { 05814 if(redirections->at(i) == dev || redirections->at(i).replacement == dev) 05815 redirections->removeAt(i); 05816 else 05817 ++i; 05818 } 05819 } 05820 }
| void qt_painter_tread_test | ( | ) |
Definition at line 4589 of file qpainter.cpp.
References QThread::currentThread(), qApp, and qWarning().
Referenced by QPainter::drawTextItem().
04590 { 04591 if (QThread::currentThread() != qApp->thread()) 04592 qWarning("QPainter: It is not safe to use text and fonts outside the GUI thread"); 04593 }
Here is the call graph for this function:

| QPixmap qt_pixmapForBrush | ( | int | style, | |
| bool | invert | |||
| ) |
Definition at line 76 of file qbrush.cpp.
References QPixmapCache::find(), QImage::Format_MonoLSB, QBitmap::fromData(), QPixmapCache::insert(), key, QString::number(), and qt_patternForBrush().
Referenced by getPatternFill(), and QX11PaintEngine::updateBrush().
00077 { 00078 QPixmap pm; 00079 QString key = QLatin1String("$qt-brush$") + QString::number(brushStyle) 00080 + QString::number((int)invert); 00081 if (!QPixmapCache::find(key, pm)) { 00082 pm = QBitmap::fromData(QSize(8, 8), qt_patternForBrush(brushStyle, invert), 00083 QImage::Format_MonoLSB); 00084 QPixmapCache::insert(key, pm); 00085 } 00086 00087 return pm; 00088 }
Here is the call graph for this function:

1.5.1