📄 qpaintengine_x11.cpp
字号:
#endif d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3; // 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 = 100; QRect devClipRect; QRegion sysClip = systemClip(); if (!sysClip.isEmpty()) { devClipRect = sysClip.boundingRect(); devClipRect.adjust(-BUFFERZONE, -BUFFERZONE, 2*BUFFERZONE, 2*BUFFERZONE); } else { devClipRect.setRect(-BUFFERZONE, -BUFFERZONE, pdev->width() + 2*BUFFERZONE, pdev->height() + 2 * BUFFERZONE); } d->polygonClipper.setBoundingRect(devClipRect); setActive(true); 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 == QPainterPrivate::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->use_path_fallback) { 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 == QPainterPrivate::TxTranslate) r.translate(offset); r = r.intersect(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 == QPainterPrivate::TxTranslate) r.translate(offset); r = r.intersect(clip); if (r.isEmpty()) continue; d->setupAdaptedOrigin(r.topLeft()); if (d->has_brush) XFillRectangle(d->dpy, d->hd, d->gc_brush, 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()); } d->resetAdaptedOrigin(); } else { QVarLengthArray<XRectangle> xrects(rectCount); int numClipped = rectCount; for (int i = 0; i < rectCount; ++i) { QRect r(rects[i]); if (d->txop == QPainterPrivate::TxTranslate) r.translate(offset); r = r.intersect(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){ Q_ASSERT(points); Q_ASSERT(pointCount); Q_D(QX11PaintEngine); if (!d->has_pen) return; if (d->cpen.widthF() > .0f || d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing)) { const QPoint *end = points + pointCount; while (points < end) { QPainterPath path; path.moveTo(*points); path.lineTo(points->x()+.005, points->y()); drawPath(path); ++points; } return; } static const int BUF_SIZE = 1024; XPoint xPoints[BUF_SIZE]; int i = 0, j = 0; while (i < pointCount) { while (i < pointCount && j < BUF_SIZE) { const QPoint &xformed = d->matrix.map(points[i]); int x = xformed.x(); int y = xformed.y(); if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) { xPoints[j].x = x; xPoints[j].y = y; ++j; } ++i; } if (j) XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin); j = 0; }}void QX11PaintEngine::drawPoints(const QPointF *points, int pointCount){ Q_ASSERT(points); Q_ASSERT(pointCount); Q_D(QX11PaintEngine); if (!d->has_pen) return; if (d->cpen.widthF() > .0f || d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing)) { const QPointF *end = points + pointCount; while (points < end) { QPainterPath path; path.moveTo(*points); path.lineTo(points->x() + 0.005, points->y()); drawPath(path); ++points; } return; } static const int BUF_SIZE = 1024; XPoint xPoints[BUF_SIZE]; int i = 0, j = 0; while (i < pointCount) { while (i < pointCount && j < BUF_SIZE) { const QPointF &xformed = d->matrix.map(points[i]); int x = qFloor(xformed.x()); int y = qFloor(xformed.y()); if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) { xPoints[j].x = x; xPoints[j].y = y; ++j; } ++i; } if (j) XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin); j = 0; }}QPainter::RenderHints QX11PaintEngine::supportedRenderHints() const{#if !defined(QT_NO_XRENDER) if (X11->use_xrender) return QPainter::Antialiasing;#endif return QFlag(0);}void QX11PaintEngine::updateState(const QPaintEngineState &state){ Q_D(QX11PaintEngine); QPaintEngine::DirtyFlags flags = state.state(); if (flags & DirtyTransform) updateMatrix(state.matrix()); if (flags & (DirtyBackground | DirtyBackgroundMode)) updateBackground(state.backgroundMode(), state.backgroundBrush()); if (flags & DirtyPen) updatePen(state.pen()); if (flags & (DirtyBrush | DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin()); if (flags & DirtyFont) updateFont(state.font()); if (state.state() & DirtyClipEnabled) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -