📄 qpaintengine_raster.cpp
字号:
&& qAlpha(data->solid.color) == 255)) { data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color); return; } } ProcessSpans blend = pe ? pe->getBrushFunc(rect, data) : data->blend; 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 = width; spans[i].y = y + i; spans[i].coverage = 255; ++i; } blend(n, spans, data); y += n; }}/*! \reimp*/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 <= QTransform::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) { resolveGradientBoundsConditional(rect, &d->brushData); QRect r = rect.translated(offset_x, offset_y); fillRect(r, &d->brushData, d); } 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); }}/*! \internal*/void QRasterPaintEngine::fastFillRect(const QRect &rect, const QBrush &brush){ Q_D(QRasterPaintEngine); Q_ASSERT(!d->antialiased && d->txop <= QTransform::TxTranslate); int offset_x = int(d->matrix.dx()); int offset_y = int(d->matrix.dy()); QSpanData brushData; brushData.init(d->rasterBuffer, this); brushData.setup(brush, d->opacity); d->updateMatrixData(&brushData, brush, d->brushMatrix()); if (!brushData.blend) return; resolveGradientBoundsConditional(rect, &brushData); QRect r = rect.translated(offset_x, offset_y); fillRect(r, &brushData, d);}/*! \reimp*/void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount){#ifdef QT_DEBUG_DRAW qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount);#endif#ifdef QT_FAST_SPANS Q_D(QRasterPaintEngine); if (d->tx_noshear) { d->rasterizer.initialize(d->antialiased, d->rasterBuffer); if (d->brushData.blend) { d->rasterizer.setSpanData(&d->brushData); for (int i = 0; i < rectCount; ++i) { const QRectF &rect = rects[i].normalized(); resolveGradientBoundsConditional(rect, &d->brushData); const QPointF a = d->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); const QPointF b = d->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f); d->rasterizer.rasterizeLine(a, b, rect.height() / rect.width()); } } if (d->penData.blend) { qreal width = d->pen.isCosmetic() ? (d->pen.widthF() == 0 ? 1 : d->pen.widthF()) : d->pen.widthF() * d->txscale; if (!d->fast_pen && width <= 1 && d->pen.style() == Qt::SolidLine) { d->rasterizer.setSpanData(&d->penData); for (int i = 0; i < rectCount; ++i) { const QRectF &rect = rects[i].normalized(); resolveGradientBoundsConditional(rect, &d->penData); const QPointF tl = d->matrix.map(rect.topLeft()); const QPointF tr = d->matrix.map(rect.topRight()); const QPointF bl = d->matrix.map(rect.bottomLeft()); const QPointF br = d->matrix.map(rect.bottomRight()); const qreal w = width / (rect.width() * d->txscale); const qreal h = width / (rect.height() * d->txscale); d->rasterizer.rasterizeLine(tl, tr, w); // top d->rasterizer.rasterizeLine(bl, br, w); // bottom d->rasterizer.rasterizeLine(bl, tl, h); // left d->rasterizer.rasterizeLine(br, tr, h); // right } } else { ProcessSpans brush_blend = d->brushData.blend; d->brushData.blend = 0; for (int i = 0; i < rectCount; ++i) { const QRectF &rf = rects[i].normalized(); QPointF pts[4] = { QPointF(rf.x(), rf.y()), QPointF(rf.x() + rf.width(), rf.y()), QPointF(rf.x() + rf.width(), rf.y() + rf.height()), QPointF(rf.x(), rf.y() + rf.height()) }; drawPolygon(pts, 4, ConvexMode); } d->brushData.blend = brush_blend; } } return; }#endif // QT_FAST_SPANS for (int i=0; i<rectCount; ++i) { const QRectF &rf = rects[i]; QPointF pts[4] = { QPointF(rf.x(), rf.y()), QPointF(rf.x() + rf.width(), rf.y()), QPointF(rf.x() + rf.width(), rf.y() + rf.height()), QPointF(rf.x(), rf.y() + rf.height()) }; drawPolygon(pts, 4, ConvexMode); }}/*! \reimp*/void QRasterPaintEngine::drawPath(const QPainterPath &path){#ifdef QT_DEBUG_DRAW QRectF bounds = path.boundingRect(); qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]", bounds.x(), bounds.y(), bounds.width(), bounds.height());#endif if (path.isEmpty()) return; Q_D(QRasterPaintEngine); if (d->brushData.blend) { d->outlineMapper->setMatrix(d->matrix, d->txop); fillPath(path, &d->brushData); } if (!d->penData.blend) return; { Q_ASSERT(d->stroker); d->outlineMapper->beginOutline(Qt::WindingFill); if (d->pen.isCosmetic()) { d->outlineMapper->setMatrix(QTransform(), QTransform::TxNone); d->stroker->strokePath(path, d->outlineMapper, d->matrix); } else { d->outlineMapper->setMatrix(d->matrix, d->txop); d->stroker->strokePath(path, d->outlineMapper, QTransform()); } d->outlineMapper->endOutline(); if (needsResolving(&d->penData)) resolveGradientBounds(path.controlPointRect(), &d->penData); ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect, &d->penData); d->rasterize(d->outlineMapper->outline(), blend, &d->penData, d->rasterBuffer); d->outlineMapper->setMatrix(d->matrix, d->txop); }}static inline bool isAbove(const QPointF *a, const QPointF *b){ return a->y() < b->y();}static bool splitPolygon(const QPointF *points, int pointCount, QVector<QPointF> *upper, QVector<QPointF> *lower){ Q_ASSERT(upper); Q_ASSERT(lower); Q_ASSERT(pointCount >= 2); QVector<const QPointF *> sorted; sorted.reserve(pointCount); upper->reserve(pointCount * 3 / 4); lower->reserve(pointCount * 3 / 4); for (int i = 0; i < pointCount; ++i) sorted << points + i; qSort(sorted.begin(), sorted.end(), isAbove); qreal splitY = sorted.at(sorted.size() / 2)->y(); const QPointF *end = points + pointCount; const QPointF *last = end - 1; QVector<QPointF> *bin[2] = { upper, lower }; for (const QPointF *p = points; p < end; ++p) { int side = p->y() < splitY; int lastSide = last->y() < splitY; if (side != lastSide) { if (qFuzzyCompare(p->y(), splitY)) { bin[!side]->append(*p); } else if (qFuzzyCompare(last->y(), splitY)) { bin[side]->append(*last); } else { QPointF delta = *p - *last; QPointF intersection(p->x() + delta.x() * (splitY - p->y()) / delta.y(), splitY); bin[0]->append(intersection); bin[1]->append(intersection); } } bin[side]->append(*p); last = p; } // give up if we couldn't reduce the point count return upper->size() < pointCount && lower->size() < pointCount;}/*! \internal */void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode){ Q_D(QRasterPaintEngine); const int maxPoints = 0xffff; // max amount of points that raster engine can reliably handle if (pointCount > maxPoints) { QVector<QPointF> upper, lower; if (splitPolygon(points, pointCount, &upper, &lower)) { fillPolygon(upper.constData(), upper.size(), mode); fillPolygon(lower.constData(), lower.size(), mode); } else qWarning("Polygon too complex for filling."); return; } // Compose polygon fill.., d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); d->outlineMapper->moveTo(*points); const QPointF *p = points; const QPointF *ep = points + pointCount - 1; do { d->outlineMapper->lineTo(*(++p)); } while (p < ep); d->outlineMapper->endOutline(); if (needsResolving(&d->brushData)) resolveGradientBoundsConditional(boundingRect(points, pointCount), &d->brushData); // scanconvert. ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &d->brushData); d->rasterize(d->outlineMapper->outline(), brushBlend, &d->brushData, d->rasterBuffer);}/*! \reimp*/void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode){ Q_D(QRasterPaintEngine);#ifdef QT_DEBUG_DRAW qDebug(" - QRasterPaintEngine::drawPolygon(), pointCount=%d", pointCount); for (int i=0; i<pointCount; ++i) qDebug() << " - " << points[i];#endif Q_ASSERT(pointCount >= 2); // Do the fill if (d->brushData.blend && mode != PolylineMode) fillPolygon(points, pointCount, mode); // Do the outline... if (d->penData.blend) { if (needsResolving(&d->penData)) resolveGradientBounds(boundingRect(points, pointCount), &d->penData); bool needs_closing = mode != PolylineMode && points[0] != points[pointCount-1]; if (d->fast_pen && d->pen.brush().isOpaque()) { // Use fast path for 0 width / trivial pens. QRect devRect(0, 0, d->deviceRect.width(), d->deviceRect.height()); LineDrawMode mode_for_last = (d->pen.capStyle() != Qt::FlatCap ? LineDrawIncludeLastPixel : LineDrawNormal); int dashOffset = int(d->pen.dashOffset()); // Draw all the line segments. for (int i=1; i<pointCount; ++i) { QPointF lp1 = points[i-1] * d->matrix; QPointF lp2 = points[i] * d->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &d->penData); if (d->pen.style() == Qt::SolidLine) { drawLine_midpoint_i(qFloor(lp1.x()), qFloor(lp1.y()), qFloor(lp2.x()), qFloor(lp2.y()), penBlend, &d->penData, i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel, devRect); } else { drawLine_midpoint_dashed_i(qFloor(lp1.x()), qFloor(lp1.y()), qFloor(lp2.x()), qFloor(lp2.y()), &d->pen, penBlend, &d->penData, i == pointCount - 1 ? mode_for_last : LineDrawIncludeLastPixel, devRect, &dashOffset); } } // Polygons are implicitly closed. if (needs_closing) { QPointF lp1 = points[pointCount-1] * d->matrix; QPointF lp2 = points[0] * d->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &d->penData); if (d->pen.style() == Qt::SolidLine) { drawLine_midpoint_i(qFloor(lp1.x()), qFloor(lp1.y()), qFloor(lp2.x()), qFloor(lp2.y()), penBlend, &d->penData, LineDrawIncludeLastPixel, devRect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -