📄 qpaintengine_x11.cpp
字号:
if (adapted_brush_origin) XSetTSOrigin(dpy, gc_brush, p.x(), p.y());}void QX11PaintEnginePrivate::resetAdaptedOrigin(){ if (adapted_pen_origin) XSetTSOrigin(dpy, gc, 0, 0); if (adapted_brush_origin) XSetTSOrigin(dpy, gc_brush, 0, 0);}void QX11PaintEnginePrivate::clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly){ int clipped_count = 0; qt_float_point *clipped_points = 0; polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(), &clipped_points, &clipped_count); clipped_poly->resize(clipped_count); for (int i=0; i<clipped_count; ++i) (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i]));}static QPaintEngine::PaintEngineFeatures qt_decide_features(){ QPaintEngine::PaintEngineFeatures features = QPaintEngine::PrimitiveTransform | QPaintEngine::PatternBrush | QPaintEngine::AlphaBlend | QPaintEngine::PainterPaths; if (X11->use_xrender) { features |= QPaintEngine::Antialiasing; features |= QPaintEngine::PorterDuff; features |= QPaintEngine::MaskedBrush;#if 0 if (X11->xrender_version > 10) { features |= QPaintEngine::LinearGradientFill; // ### }#endif } return features;}/* * QX11PaintEngine members */QX11PaintEngine::QX11PaintEngine() : QPaintEngine(*(new QX11PaintEnginePrivate), qt_decide_features()){ d_func()->init();}QX11PaintEngine::QX11PaintEngine(QX11PaintEnginePrivate &dptr) : QPaintEngine(dptr, qt_decide_features()){ d_func()->init();}QX11PaintEngine::~QX11PaintEngine(){#ifndef QT_NO_XRENDER Q_D(QX11PaintEngine); delete d->tessellator;#endif}bool QX11PaintEngine::begin(QPaintDevice *pdev){ Q_D(QX11PaintEngine); d->xinfo = qt_x11Info(pdev);#ifndef QT_NO_XRENDER if (pdev->devType() == QInternal::Widget) { d->picture = (::Picture)static_cast<const QWidget *>(pdev)->x11PictureHandle(); } else if (pdev->devType() == QInternal::Pixmap) { const QPixmap *pm = static_cast<const QPixmap *>(pdev); if (X11->use_xrender && pm->data->d != 32 && pm->data->x11_mask) pm->data->convertToARGB32(); d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle(); }#else d->picture = 0;#endif d->hd = qt_x11Handle(pdev); Q_ASSERT(d->xinfo != 0); d->dpy = d->xinfo->display(); // get display variable d->scrn = d->xinfo->screen(); // get screen variable d->crgn = QRegion(); d->gc = XCreateGC(d->dpy, d->hd, 0, 0); d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0); d->has_alpha_brush = false; d->has_alpha_pen = false; d->has_clipping = false; d->has_complex_xform = false; d->has_custom_pen = false; d->matrix = QTransform(); d->pdev_depth = d->pdev->depth(); d->render_hints = 0; d->txop = QTransform::TxNone; d->use_path_fallback = false;#if !defined(QT_NO_XRENDER) d->composition_mode = PictOpOver;#endif d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3; d->opacity = 1; // Set up the polygon clipper. Note: This will only work in // polyline mode as long as we have a buffer zone, since a // polyline may be clipped into several non-connected polylines. const int BUFFERZONE = 1000; QRect devClipRect(-BUFFERZONE, -BUFFERZONE, pdev->width() + 2*BUFFERZONE, pdev->height() + 2*BUFFERZONE); d->polygonClipper.setBoundingRect(devClipRect); QPixmap::x11SetDefaultScreen(d->xinfo->screen()); QWidget *w = d->pdev->devType() == QInternal::Widget ? static_cast<QWidget *>(d->pdev) : 0; if (w && w->testAttribute(Qt::WA_PaintUnclipped)) { // paint direct on device updatePen(QPen(Qt::black)); updateBrush(QBrush(Qt::white), QPoint()); XSetSubwindowMode(d->dpy, d->gc, IncludeInferiors); XSetSubwindowMode(d->dpy, d->gc_brush, IncludeInferiors);#ifndef QT_NO_XRENDER XRenderPictureAttributes attrs; attrs.subwindow_mode = IncludeInferiors; XRenderChangePicture(d->dpy, d->picture, CPSubwindowMode, &attrs);#endif } setDirty(QPaintEngine::DirtyClipRegion); setDirty(QPaintEngine::DirtyPen); setDirty(QPaintEngine::DirtyBrush); setDirty(QPaintEngine::DirtyBackground); return true;}bool QX11PaintEngine::end(){ Q_D(QX11PaintEngine);#if !defined(QT_NO_XRENDER) if (d->picture) { // reset clipping/subwindow mode on our render picture XRenderPictureAttributes attrs; attrs.subwindow_mode = ClipByChildren; attrs.clip_mask = XNone; XRenderChangePicture(d->dpy, d->picture, CPClipMask|CPSubwindowMode, &attrs); }#endif if (d->gc_brush && d->pdev->painters < 2) { XFreeGC(d->dpy, d->gc_brush); d->gc_brush = 0; } if (d->gc && d->pdev->painters < 2) { XFreeGC(d->dpy, d->gc); d->gc = 0; } return true;}static bool clipLine(QLineF *line, const QRect &rect){ qreal x1 = line->x1(); qreal x2 = line->x2(); qreal y1 = line->y1(); qreal y2 = line->y2(); qreal left = rect.x(); qreal right = rect.x() + rect.width() - 1; qreal top = rect.y(); qreal bottom = rect.y() + rect.height() - 1; enum { Left, Right, Top, Bottom }; // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html int p1 = ((x1 < left) << Left) | ((x1 > right) << Right) | ((y1 < top) << Top) | ((y1 > bottom) << Bottom); int p2 = ((x2 < left) << Left) | ((x2 > right) << Right) | ((y2 < top) << Top) | ((y2 > bottom) << Bottom); if (p1 & p2) // completely outside return false; if (p1 | p2) { qreal dx = x2 - x1; qreal dy = y2 - y1; // clip x coordinates if (x1 < left) { y1 += dy/dx * (left - x1); x1 = left; } else if (x1 > right) { y1 -= dy/dx * (x1 - right); x1 = right; } if (x2 < left) { y2 += dy/dx * (left - x2); x2 = left; } else if (x2 > right) { y2 -= dy/dx * (x2 - right); x2 = right; } p1 = ((y1 < top) << Top) | ((y1 > bottom) << Bottom); p2 = ((y2 < top) << Top) | ((y2 > bottom) << Bottom); if (p1 & p2) return false; // clip y coordinates if (y1 < top) { x1 += dx/dy * (top - y1); y1 = top; } else if (y1 > bottom) { x1 -= dx/dy * (y1 - bottom); y1 = bottom; } if (y2 < top) { x2 += dx/dy * (top - y2); y2 = top; } else if (y2 > bottom) { x2 -= dx/dy * (y2 - bottom); y2 = bottom; } *line = QLineF(QPointF(x1, y1), QPointF(x2, y2)); } return true;}void QX11PaintEngine::drawLines(const QLine *lines, int lineCount){ Q_ASSERT(lines); Q_ASSERT(lineCount); Q_D(QX11PaintEngine); if (d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->cpen.widthF() > 0 && d->has_complex_xform) || (d->render_hints & QPainter::Antialiasing)) { for (int i = 0; i < lineCount; ++i) { QPainterPath path(lines[i].p1()); path.lineTo(lines[i].p2()); drawPath(path); } return; } if (d->has_pen) { for (int i = 0; i < lineCount; ++i) { QLineF linef; if (d->txop == QTransform::TxNone) { linef = lines[i]; } else { linef = QLineF(d->matrix.map(lines[i].p1()), d->matrix.map(lines[i].p2())); } if (clipLine(&linef, d->polygonClipper.boundingRect())) { XDrawLine(d->dpy, d->hd, d->gc, qFloor(linef.x1()), qFloor(linef.y1()), qFloor(linef.x2()), qFloor(linef.y2())); } } }}void QX11PaintEngine::drawRects(const QRect *rects, int rectCount){ Q_D(QX11PaintEngine); Q_ASSERT(rects); Q_ASSERT(rectCount); if (d->has_alpha_pen || d->has_complex_xform || (d->render_hints & QPainter::Antialiasing)) { for (int i = 0; i < rectCount; ++i) { QPainterPath path; path.addRect(rects[i]); drawPath(path); } return; } QRect clip(d->polygonClipper.boundingRect()); QPoint offset(qRound(d->matrix.dx()), qRound(d->matrix.dy()));#if !defined(QT_NO_XRENDER) ::Picture pict = d->picture; if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1 && (d->has_texture || d->has_alpha_brush)) { XRenderColor xc; if (!d->has_texture && !d->has_pattern) xc = X11->preMultiply(d->cbrush.color()); for (int i = 0; i < rectCount; ++i) { QRect r(rects[i]); if (d->txop == QTransform::TxTranslate) r.translate(offset); r = r.intersected(clip); if (r.isEmpty()) continue; if (d->has_texture || d->has_pattern) { XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict, qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()), 0, 0, r.x(), r.y(), r.width(), r.height()); } else { XRenderFillRectangle(d->dpy, d->composition_mode, pict, &xc, r.x(), r.y(), r.width(), r.height()); } if (d->has_pen) XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height()); } } else#endif // !QT_NO_XRENDER { if (d->has_brush && d->has_pen) { for (int i = 0; i < rectCount; ++i) { QRect r(rects[i]); if (d->txop == QTransform::TxTranslate) r.translate(offset); r = r.intersected(clip); if (r.isEmpty()) continue; d->setupAdaptedOrigin(r.topLeft()); XFillRectangle(d->dpy, d->hd, d->gc_brush, r.x(), r.y(), r.width(), r.height()); XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height()); } d->resetAdaptedOrigin(); } else { QVarLengthArray<XRectangle> xrects(rectCount); int numClipped = rectCount; for (int i = 0; i < rectCount; ++i) { QRect r(rects[i]); if (d->txop == QTransform::TxTranslate) r.translate(offset); r = r.intersected(clip); if (r.isEmpty()) { --numClipped; continue; } xrects[i].x = short(r.x()); xrects[i].y = short(r.y()); xrects[i].width = ushort(r.width()); xrects[i].height = ushort(r.height()); } if (numClipped) { d->setupAdaptedOrigin(rects[0].topLeft()); if (d->has_brush && !d->has_pen) XFillRectangles(d->dpy, d->hd, d->gc_brush, xrects.data(), numClipped); else if (d->has_pen && !d->has_brush) XDrawRectangles(d->dpy, d->hd, d->gc, xrects.data(), numClipped); d->resetAdaptedOrigin(); } } }}void QX11PaintEngine::drawPoints(const QPoint *points, int pointCount){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -