src/gui/painting/qpainter.cpp File Reference

#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< QPaintDeviceRedirectionQPaintDeviceRedirectionList

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 Documentation

#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().


Typedef Documentation

typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList

Definition at line 5729 of file qpainter.cpp.


Function Documentation

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().

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:


Generated on Thu Mar 15 13:35:17 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1