⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qpainter.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/// QtCore#include <qdebug.h>#include <qmutex.h>// QtGui#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 <private/qmath_p.h>#define QGradient_StretchToDevice 0x10000000#define QPaintEngine_OpaqueBackground 0x40000000// #define QT_DEBUG_DRAW#ifdef QT_DEBUG_DRAWbool qt_show_painter_debug_output = true;#endifextern 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);/* Returns true if the gradient requires stretch to device...*/static inline bool check_gradient(const QBrush &brush){    switch (brush.style()) {    case Qt::LinearGradientPattern:    case Qt::RadialGradientPattern:    case Qt::ConicalGradientPattern:        if (brush.gradient()->coordinateMode() == QGradient::StretchToDeviceMode)            return true;    default:        ;    }    return false;}static inline bool is_brush_transparent(const QBrush &brush) {    Qt::BrushStyle s = brush.style();    return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)            || (s == Qt::TexturePattern && brush.texture().isQBitmap()));}static inline bool is_pen_transparent(const QPen &pen) {    return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());}/* Discards the emulation flags that are not relevant for line drawing   and returns the result*/static inline uint line_emulation(uint emulation){    return emulation & (QPaintEngine::PrimitiveTransform                        | QPaintEngine::AlphaBlend                        | QPaintEngine::Antialiasing                        | QPaintEngine::BrushStroke                        | QPaintEngine::ConstantOpacity                        | QGradient_StretchToDevice                        | QPaintEngine_OpaqueBackground);}QTransform QPainterPrivate::viewTransform() const{    QTransform m;    if (state->VxF) {        qreal scaleW = qreal(state->vw)/qreal(state->ww);        qreal scaleH = qreal(state->vh)/qreal(state->wh);        m.setMatrix(scaleW, 0, 0,                    0, scaleH, 0,                    state->vx - state->wx*scaleW, state->vy - state->wy*scaleH, 1);    }    return m;}void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op){#ifdef QT_DEBUG_DRAW    if (qt_show_painter_debug_output) {        printf("QPainter::drawHelper\n");    }#endif    if (originalPath.isEmpty())        return;    if (state->emulationSpecifier == QGradient_StretchToDevice) {        drawStretchToDevice(originalPath, op);        return;    } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {        drawOpaqueBackground(originalPath, op);        return;    }    Q_Q(QPainter);    int devMinX = 0, devMaxX = 0, devMinY = 0, devMaxY = 0;    qreal strokeOffsetX = 0, strokeOffsetY = 0;    QPainterPath path = originalPath * state->matrix;    QRectF pathBounds = path.boundingRect();    QRectF strokeBounds;    bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);    if (doStroke) {        qreal penWidth = state->pen.widthF();        if (penWidth == 0) {            strokeOffsetX = 1;            strokeOffsetY = 1;        } else {            // In case of complex xform            if (state->txop > QTransform::TxScale) {                QPainterPathStroker stroker;                stroker.setWidth(penWidth);                stroker.setJoinStyle(state->pen.joinStyle());                stroker.setCapStyle(state->pen.capStyle());                QPainterPath stroke = stroker.createStroke(originalPath);                strokeBounds = (stroke * state->matrix).boundingRect();            } else {                strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);                strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);            }        }    }    const qreal ROUND_UP_TRICK = 0.9999;    if (!strokeBounds.isEmpty()) {        devMinX = int(strokeBounds.left());        devMaxX = int(strokeBounds.right() + ROUND_UP_TRICK);        devMinY = int(strokeBounds.top());        devMaxY = int(strokeBounds.bottom() + ROUND_UP_TRICK);    } else {        devMinX = int(pathBounds.left() - strokeOffsetX);        devMaxX = int(pathBounds.right() + strokeOffsetX + ROUND_UP_TRICK);        devMinY = int(pathBounds.top() - strokeOffsetY);        devMaxY = int(pathBounds.bottom() + strokeOffsetY + ROUND_UP_TRICK);    }    QRect absPathRect(devMinX, devMinY, devMaxX - devMinX, devMaxY - devMinY);    if (state->clipInfo.size() != 0) {        QPainterPath clipPath = q->clipPath() * q->deviceTransform();        QRectF r = clipPath.boundingRect().intersected(absPathRect);        absPathRect.setCoords(qFloor(r.left()), qFloor(r.top()),                              qCeil(r.right()), qCeil(r.bottom()));    }    absPathRect = absPathRect.intersected(QRect(0, 0, device->width(), device->height()));//     qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",//            devMinX, devMinY, device->width(), device->height());//     qDebug() << " - matrix" << state->matrix;//     qDebug() << " - originalPath.bounds" << originalPath.boundingRect();//     qDebug() << " - path.bounds" << path.boundingRect();    if (absPathRect.width() <= 0 || absPathRect.height() <= 0)        return;    QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);    image.fill(0);    QPainter p(&image);    p.d_ptr->original_device = original_device;    p.setOpacity(state->opacity);    p.translate(-absPathRect.x(), -absPathRect.y());    p.setTransform(state->matrix, true);    p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));    p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));    p.setBackground(state->bgBrush);    p.setBackgroundMode(state->bgMode);    p.setBrushOrigin(state->bgOrigin);    p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);    p.setRenderHint(QPainter::SmoothPixmapTransform,                    state->renderHints & QPainter::SmoothPixmapTransform);    p.drawPath(originalPath);    p.end();    q->save();    q->resetMatrix();    updateState(state);    engine->drawImage(absPathRect,                 image,                 QRectF(0, 0, absPathRect.width(), absPathRect.height()),                 Qt::OrderedDither | Qt::OrderedAlphaDither);    q->restore();}void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op){    Q_Q(QPainter);    q->setBackgroundMode(Qt::TransparentMode);    if (op & FillDraw && state->brush.style() != Qt::NoBrush) {        q->fillPath(path, state->bgBrush.color());        q->fillPath(path, state->brush);    }    if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {        q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));        q->strokePath(path, state->pen);    }    q->setBackgroundMode(Qt::OpaqueMode);}void QPainterPrivate::drawStretchToDevice(const QPainterPath &path, DrawOperation op){    Q_Q(QPainter);    double sw = original_device->width();    double sh = original_device->height();    QTransform inv(1.0/sw, 0, 0, 1.0/sh, 0, 0);    QPen pen = state->pen;    QBrush brush = state->brush;    if ((op & FillDraw) && brush.style() == Qt::NoBrush) op = DrawOperation(op - FillDraw);    if ((op & StrokeDraw) && pen.style() == Qt::NoPen) op = DrawOperation(op - StrokeDraw);    q->scale(sw, sh);    q->setPen(Qt::NoPen);    updateState(state);    // Draw the xformed fill if the brush is a stretch gradient.    if ((op & FillDraw) && check_gradient(brush)) {        engine->drawPath(path * inv);        op = DrawOperation(op - FillDraw);    }    // Draw the xformed outline if the pen is a stretch gradient.    if ((op & StrokeDraw) && check_gradient(pen.brush())) {        q->setBrush(pen.brush());        updateState(state);        QPainterPathStroker stroker;        stroker.setDashPattern(pen.style());        stroker.setWidth(pen.widthF());        stroker.setJoinStyle(pen.joinStyle());        stroker.setCapStyle(pen.capStyle());        stroker.setMiterLimit(pen.miterLimit());        QPainterPath stroke = stroker.createStroke(path);        engine->drawPath(stroke * inv);        op = DrawOperation(op - StrokeDraw);    }    q->scale(1/sw, 1/sh);    if (op & FillDraw) {        updateState(state);        engine->drawPath(path);    }    q->setPen(pen);    if (op & StrokeDraw) {        q->setBrush(Qt::NoBrush);        updateState(state);        engine->drawPath(path);        q->setBrush(brush);    }}void QPainterPrivate::init(){    Q_Q(QPainter);    state->painter = q;}void QPainterPrivate::updateMatrix(){    state->matrix = (state->WxF ? state->worldMatrix : QTransform())                    * (state->VxF ? viewTransform() : QTransform());    txinv = false;                                // no inverted matrix    state->txop = static_cast<int>(state->matrix.type());    if (!redirection_offset.isNull()) {        state->txop |= QTransform::TxTranslate;        // We want to translate in dev space so we do the adding of the redirection        // offset manually.        if (state->matrix.isAffine()) {            state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(),                                       state->matrix.m21(), state->matrix.m22(),                                       state->matrix.dx()-redirection_offset.x(),                                       state->matrix.dy()-redirection_offset.y());        } else {            QTransform temp;            temp.translate(-redirection_offset.x(), -redirection_offset.y());            state->matrix *= temp;        }    }    state->dirtyFlags |= QPaintEngine::DirtyTransform;//     printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);//     qDebug() << " --- using matrix" << state->matrix << redirection_offset;}/*! \internal */void QPainterPrivate::updateInvMatrix(){    Q_ASSERT(txinv == false);    txinv = true;                                // creating inverted matrix    bool invertible;    QTransform m;    if (state->VxF) {        m.translate(state->vx, state->vy);        m.scale(1.0*state->vw/state->ww, 1.0*state->vh/state->wh);        m.translate(-state->wx, -state->wy);    }    if (state->WxF) {        if (state->VxF)            m = state->worldMatrix * m;        else            m = state->worldMatrix;    }    invMatrix = m.inverted(&invertible);                // invert matrix}void QPainterPrivate::updateEmulationSpecifier(QPainterState *s){    bool alpha = false;    bool linearGradient = false;    bool radialGradient = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -