📄 qpaintengine_raster.cpp
字号:
{ Q_D(QRasterPaintEngine); delete d->rasterBuffer; d->rasterBuffer = new QRasterBuffer;}QSize QRasterPaintEngine::size() const{ Q_D(const QRasterPaintEngine); return QSize(d->rasterBuffer->width(), d->rasterBuffer->height());}#ifndef QT_NO_DEBUGvoid QRasterPaintEngine::saveBuffer(const QString &s) const{ Q_D(const QRasterPaintEngine); d->rasterBuffer->bufferImage().save(s, "PNG");}#endifvoid QRasterPaintEngine::setFlushOnEnd(bool flushOnEnd){ Q_D(QRasterPaintEngine); d->flushOnEnd = flushOnEnd;}/*! Force the contents of the buffer out on the underlying device.*/void QRasterPaintEngine::flush(QPaintDevice *device, const QPoint &offset){ Q_D(QRasterPaintEngine); Q_ASSERT(device);#if defined(Q_WS_WIN) if (!d->rasterBuffer->hdc()) return; if (device->devType() == QInternal::Widget) { HDC hdc = device->getDC(); bool tmp_hdc = false; if (!hdc) { tmp_hdc = true; hdc = GetDC(((QWidget*) device)->winId()); } QRegion sysClip = systemClip(); if (sysClip.isEmpty()) { BitBlt(hdc, d->deviceRect.x() + offset.x(), d->deviceRect.y() + offset.y(), d->deviceRect.width(), d->deviceRect.height(), d->rasterBuffer->hdc(), 0, 0, SRCCOPY); } else { QVector<QRect> rects = sysClip.rects(); for (int i=0; i<rects.size(); ++i) { QRect r = rects.at(i); BitBlt(hdc, r.x() + offset.x(), r.y() + offset.y(), r.width(), r.height(), d->rasterBuffer->hdc(), r.x() - d->deviceRect.x(), r.y() - d->deviceRect.y(), SRCCOPY); } } if (tmp_hdc) { ReleaseDC(((QWidget *) device)->winId(), hdc); } else { device->releaseDC(hdc); } }#elif defined(Q_WS_MAC)# ifdef QMAC_NO_COREGRAPHICS# warning "unhandled"# else extern CGContextRef qt_macCreateCGHandle(const QPaintDevice *); //qpaintdevice_mac.cpp extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp if(CGContextRef ctx = qt_mac_cg_context(device)) { CGRect rect = CGRectMake(d->deviceRect.x(), d->deviceRect.y(), d->deviceRect.width(), d->deviceRect.height()); HIViewDrawCGImage(ctx, &rect, d->rasterBuffer->m_data); //top left CGContextRelease(ctx); }# endif Q_UNUSED(offset);#else Q_UNUSED(d); Q_UNUSED(offset); Q_UNUSED(device);#endif}void QRasterPaintEngine::updateMatrix(const QMatrix &matrix){ Q_D(QRasterPaintEngine); d->matrix = matrix; d->int_xform = false; if (d->matrix.m12() != 0 || d->matrix.m21() != 0) { d->txop = QPainterPrivate::TxRotShear; } else if (d->matrix.m11() != 1 || d->matrix.m22() != 1) { d->txop = QPainterPrivate::TxScale; d->int_xform = qreal(int(d->matrix.dx())) == d->matrix.dx() && qreal(int(d->matrix.dy())) == d->matrix.dy() && qreal(int(d->matrix.m11())) == d->matrix.m11() && qreal(int(d->matrix.m22())) == d->matrix.m22(); } else if (d->matrix.dx() != 0 || d->matrix.dy() != 0) { d->txop = QPainterPrivate::TxTranslate; d->int_xform = qreal(int(d->matrix.dx())) == d->matrix.dx() && qreal(int(d->matrix.dy())) == d->matrix.dy(); } else { d->txop = QPainterPrivate::TxNone; d->int_xform = true; } // 1/10000 == 0.0001, so we have good enough res to cover curves // that span the entire widget... d->inverseScale = qMax(1 / qMax( qMax(qAbs(matrix.m11()), qAbs(matrix.m22())), qMax(qAbs(matrix.m12()), qAbs(matrix.m21())) ), qreal(0.0001)); d->outlineMapper->setMatrix(d->matrix, d->txop); d->penData.setupMatrix(d->matrix, d->txop, d->bilinear); d->brushData.setupMatrix(d->brushMatrix(), d->txop, d->bilinear);}void QRasterPaintEngine::updateState(const QPaintEngineState &state){ Q_D(QRasterPaintEngine); QPaintEngine::DirtyFlags flags = state.state(); bool update_fast_pen = false; if (flags & DirtyTransform) { update_fast_pen = true; updateMatrix(state.matrix()); } if (flags & DirtyBackgroundMode) { d->rasterBuffer->opaqueBackground = (state.backgroundMode() == Qt::OpaqueMode); } if (flags & DirtyBackground) { d->rasterBuffer->bgBrush = state.backgroundBrush(); } if (flags & DirtyPen) { update_fast_pen = true; d->pen = state.pen(); d->basicStroker.setJoinStyle(d->pen.joinStyle()); d->basicStroker.setCapStyle(d->pen.capStyle()); d->basicStroker.setMiterLimit(d->pen.miterLimit()); qreal penWidth = d->pen.widthF(); if (penWidth == 0) d->basicStroker.setStrokeWidth(1); else d->basicStroker.setStrokeWidth(penWidth); Qt::PenStyle pen_style = d->pen.style(); if(pen_style == Qt::SolidLine) { d->stroker = &d->basicStroker; } else if (pen_style != Qt::NoPen) { if (!d->dashStroker) d->dashStroker = new QDashStroker(&d->basicStroker); if (penWidth == 0) { d->dashStroker->setClipRect(d->deviceRect); } else { QRectF clipRect = d->matrix.inverted().mapRect(QRectF(d->deviceRect)); d->dashStroker->setClipRect(clipRect); } d->dashStroker->setDashPattern(d->pen.dashPattern()); d->stroker = d->dashStroker; } else { d->stroker = 0; } d->penData.setup(pen_style == Qt::NoPen ? QBrush() : d->pen.brush()); } if (flags & DirtyBrush) { QBrush brush = state.brush(); d->brush = brush; d->brushData.setup(d->brush); } if (flags & DirtyBrushOrigin) { d->brushOffset = state.brushOrigin(); d->brushData.setupMatrix(d->brushMatrix(), d->txop, d->bilinear); } if (flags & (DirtyClipPath | DirtyClipRegion)) { d->user_clip_enabled = true; // If we're setting a clip, we kill the old clip if (d->rasterBuffer->disabled_clip) { delete d->rasterBuffer->disabled_clip; d->rasterBuffer->disabled_clip = 0; } } if (flags & DirtyClipPath) { updateClipPath(state.clipPath(), state.clipOperation()); } else if (flags & DirtyClipRegion) { updateClipRegion(state.clipRegion(), state.clipOperation()); } else if (flags & DirtyClipEnabled) { if (state.isClipEnabled() != d->user_clip_enabled) { d->user_clip_enabled = state.isClipEnabled(); // The tricky case... When we disable clipping we still do // system clip so we need to rasterize the system clip and // replace the current clip with it. Since people might // choose to set clipping to true later on we have to the // current one (in disabled_clip). if (!d->baseClip.isEmpty()) { if (!state.isClipEnabled()) { // save current clip for later Q_ASSERT(!d->rasterBuffer->disabled_clip); d->rasterBuffer->disabled_clip = d->rasterBuffer->clip; d->rasterBuffer->clip = 0; updateClipPath(QPainterPath(), Qt::NoClip); } else { // re-enable old clip Q_ASSERT(d->rasterBuffer->disabled_clip); d->rasterBuffer->resetClip(); d->rasterBuffer->clip = d->rasterBuffer->disabled_clip; d->rasterBuffer->disabled_clip = 0; } } d->penData.adjustSpanMethods(); d->brushData.adjustSpanMethods(); } } if (!d->mono_surface) { if (flags & DirtyHints) { update_fast_pen = true; d->antialiased = bool(state.renderHints() & QPainter::Antialiasing); d->bilinear = bool(state.renderHints() & QPainter::SmoothPixmapTransform); // propegate state to data's d->brushData.bilinear = d->penData.bilinear = d->bilinear; d->penData.adjustSpanMethods(); d->brushData.adjustSpanMethods(); } if (flags & DirtyCompositionMode) { d->rasterBuffer->compositionMode = state.compositionMode(); } } if (update_fast_pen) { d->fast_pen = !d->antialiased && (d->pen.widthF() == 0 || d->pen.widthF() <= 1 && d->txop <= QPainterPrivate::TxTranslate); }}void QRasterPaintEngine::updateClipRegion(const QRegion &r, Qt::ClipOperation op){#ifdef QT_DEBUG_DRAW qDebug() << " - QRasterPaintEngine::updateClipRegion() op=" << op << r;#endif QPainterPath p; p.addRegion(r); updateClipPath(p, op);}void QRasterPaintEngine::updateClipPath(const QPainterPath &path, Qt::ClipOperation op){ Q_D(QRasterPaintEngine);#ifdef QT_DEBUG_DRAW qDebug() << " - QRasterPaintEngine::updateClipPath(), op=" << op << path.boundingRect();#endif d->updateClip_helper(path, op); // Reset the baseClip if the operation requires it. if (!d->baseClip.isEmpty()) { switch (op) { case Qt::UniteClip: case Qt::ReplaceClip: case Qt::NoClip: d->outlineMapper->setMatrix(QMatrix(), QPainterPrivate::TxNone); d->updateClip_helper(d->baseClip, Qt::IntersectClip); d->outlineMapper->setMatrix(d->matrix, d->txop); break; default: break; } }}void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData){#ifdef QT_DEBUG_DRAW qDebug() << " --- fillPath, bounds=" << path.boundingRect();#endif if (!fillData->blend) return; Q_D(QRasterPaintEngine); d->rasterize(d->outlineMapper->convertPath(path), fillData->blend, fillData, d->rasterBuffer);}static void fillRect(const QRect &r, QSpanData *data){ QRect rect = r.normalized(); int x1 = qMax(rect.x(), 0); int x2 = qMin(rect.width() + rect.x(), data->rasterBuffer->width()); int y1 = qMax(rect.y(), 0); int y2 = qMin(rect.height() + rect.y(), data->rasterBuffer->height()); QClipData *clip = data->rasterBuffer->clipEnabled ? data->rasterBuffer->clip : 0; if (clip) { x1 = qMax(x1, clip->xmin); x2 = qMin(x2, clip->xmax); y1 = qMax(y1, clip->ymin); y2 = qMin(y2, clip->ymax); } int len = x2 - x1; if (len > 0) { const int nspans = 256; QT_FT_Span spans[nspans]; Q_ASSERT(data->blend); int y = y1; while (y < y2) { int n = qMin(nspans, y2 - y); int i = 0; while (i < n) { spans[i].x = x1; spans[i].len = len; spans[i].y = y + i; spans[i].coverage = 255; ++i; } data->blend(n, spans, data); y += n; } }}void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount){#ifdef QT_DEBUG_DRAW qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount);#endif Q_D(QRasterPaintEngine); if (!d->antialiased && d->txop <= QPainterPrivate::TxTranslate) { int offset_x = int(d->matrix.dx()); int offset_y = int(d->matrix.dy()); const QRect *lastRect = rects + rectCount; while (rects < lastRect) { QRect rect = rects->normalized(); if (d->brushData.blend) { QRect r = rect.translated(offset_x, offset_y); fillRect(r, &d->brushData); } if (d->penData.blend) { ProcessSpans brush_blend = d->brushData.blend; d->brushData.blend = 0; int left = rect.x(); int right = rect.x() + rect.width(); int top = rect.y(); int bottom = rect.y() + rect.height(); QPoint pts[] = { QPoint(left, top), QPoint(right, top), QPoint(right, bottom), QPoint(left, bottom) }; QRasterPaintEngine::drawPolygon(pts, 4, WindingMode); d->brushData.blend = brush_blend; } ++rects; } } else { QPaintEngine::drawRects(rects, rectCount); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -