📄 qpaintengine_x11.cpp
字号:
if (d->has_pattern || d->has_texture) { if (bs == Qt::TexturePattern) { d->brush_pm = d->cbrush.texture();#if !defined(QT_NO_XRENDER) if (X11->use_xrender) { XRenderPictureAttributes attrs; attrs.repeat = true; XRenderChangePicture(d->dpy, d->brush_pm.x11PictureHandle(), CPRepeat, &attrs); if (d->brush_pm.data->mask_picture) XRenderChangePicture(d->dpy, d->brush_pm.data->mask_picture, CPRepeat, &attrs); }#endif } else { d->brush_pm = qt_pixmapForBrush(bs, true); } d->brush_pm.x11SetScreen(d->scrn); if (d->brush_pm.depth() == 1) { mask |= GCStipple; vals.stipple = d->brush_pm.handle(); s = FillStippled;#if !defined(QT_NO_XRENDER) if (X11->use_xrender) { d->bitmap_texture = QPixmap(d->brush_pm.size()); d->bitmap_texture.fill(Qt::transparent); ::Picture src = X11->getSolidFill(d->scrn, d->cbrush.color()); XRenderComposite(d->dpy, PictOpSrc, src, d->brush_pm.x11PictureHandle(), d->bitmap_texture.x11PictureHandle(), 0, 0, d->brush_pm.width(), d->brush_pm.height(), 0, 0, d->brush_pm.width(), d->brush_pm.height()); XRenderPictureAttributes attrs; attrs.repeat = true; XRenderChangePicture(d->dpy, d->bitmap_texture.x11PictureHandle(), CPRepeat, &attrs); d->current_brush = d->bitmap_texture.x11PictureHandle(); }#endif } else { mask |= GCTile;#ifndef QT_NO_XRENDER if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) d->brush_pm.data->convertToARGB32();#endif vals.tile = (d->brush_pm.depth() == d->pdev_depth ? d->brush_pm.handle() : d->brush_pm.data->x11ConvertToDefaultDepth()); s = FillTiled;#if !defined(QT_NO_XRENDER) d->current_brush = d->cbrush.texture().x11PictureHandle();#endif } mask |= GCTileStipXOrigin | GCTileStipYOrigin; vals.ts_x_origin = qRound(origin.x()); vals.ts_y_origin = qRound(origin.y()); }#if !defined(QT_NO_XRENDER) else if (d->has_alpha_brush) { d->current_brush = X11->getSolidFill(d->scrn, d->cbrush.color()); }#endif vals.fill_style = s; XChangeGC(d->dpy, d->gc_brush, mask, &vals); if (!d->has_clipping) { QRegion sysClip = systemClip(); if (!sysClip.isEmpty()) x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip); else x11ClearClipRegion(d->dpy, d->gc_brush, 0, d->picture); }}void QX11PaintEngine::drawEllipse(const QRect &rect){ Q_D(QX11PaintEngine); QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1); QRect r(rect); if (d->txop == QTransform::TxTranslate) r.translate(qRound(d->matrix.dx()), qRound(d->matrix.dy())); if (d->use_path_fallback || devclip.intersected(r) != r) { QPainterPath path; path.addEllipse(rect); drawPath(path); return; } int x = r.x(); int y = r.y(); int w = r.width(); int h = r.height(); if (w < 1 || h < 1) return; if (w == 1 && h == 1) { XDrawPoint(d->dpy, d->hd, d->has_pen ? d->gc : d->gc_brush, x, y); return; } d->setupAdaptedOrigin(rect.topLeft()); if (d->has_brush) { // draw filled ellipse if (!d->has_pen) { XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64); XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64); return; } else{ XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64); } } if (d->has_pen) // draw outline XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64); d->resetAdaptedOrigin();}void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints, int pointCount, QX11PaintEnginePrivate::GCMode gcMode, QPaintEngine::PolygonDrawMode mode){ QVarLengthArray<QPointF> translated_points(pointCount); QPointF offset(matrix.dx(), matrix.dy()); for (int i = 0; i < pointCount; ++i) translated_points[i] = polygonPoints[i] + offset; fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode);}#ifndef QT_NO_XRENDERstatic void qt_XRenderCompositeTrapezoids(Display *dpy, int op, Picture src, Picture dst, _Xconst XRenderPictFormat *maskFormat, int xSrc, int ySrc, const XTrapezoid *traps, int size){ const int MAX_TRAPS = 50000; while (size) { int to_draw = size; if (to_draw > MAX_TRAPS) to_draw = MAX_TRAPS; XRenderCompositeTrapezoids(dpy, op, src, dst, maskFormat, xSrc, ySrc, traps, to_draw); size -= to_draw; traps += to_draw; }}#endifvoid QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount, QX11PaintEnginePrivate::GCMode gcMode, QPaintEngine::PolygonDrawMode mode){ int clippedCount = 0; qt_float_point *clippedPoints = 0;#ifndef QT_NO_XRENDER //can change if we switch to pen if gcMode != BrushGC bool has_fill_texture = has_texture; bool has_fill_pattern = has_pattern; ::Picture src;#endif QBrush fill; GC fill_gc; if (gcMode == BrushGC) { fill = cbrush; fill_gc = gc_brush;#ifndef QT_NO_XRENDER if (current_brush) src = current_brush; else src = X11->getSolidFill(scrn, fill.color());#endif } else { fill = QBrush(cpen.brush()); fill_gc = gc;#ifndef QT_NO_XRENDER //we use the pens brush has_fill_texture = (fill.style() == Qt::TexturePattern); has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern); if (has_fill_texture) src = fill.texture().x11PictureHandle(); else if (has_fill_pattern) src = getPatternFill(scrn, fill); else src = X11->getSolidFill(scrn, fill.color());#endif } polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount, &clippedPoints, &clippedCount);#ifndef QT_NO_XRENDER bool solid_fill = fill.color().alpha() == 255; if (has_fill_texture && fill.texture().depth() == 1 && solid_fill) { has_fill_texture = false; has_fill_pattern = true; } bool antialias = render_hints & QPainter::Antialiasing; if (X11->use_xrender && picture && !has_fill_pattern && (clippedCount > 0) && (fill.style() != Qt::NoBrush) && (has_fill_texture && fill.texture().hasAlpha() || antialias || !solid_fill || has_alpha_pen != has_alpha_brush)) { QRect br = tessellator->tessellate((QPointF *)clippedPoints, clippedCount, mode == QPaintEngine::WindingMode); if (tessellator->size > 0) { XRenderPictureAttributes attrs; attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp; XRenderChangePicture(dpy, picture, CPPolyEdge, &attrs); if (has_fill_texture) { if (fill.texture().depth() == 1) { for (int i=0; i < tessellator->size; ++i) { int x_offset = int(XFixedToDouble(tessellator->traps[i].left.p1.x) - bg_origin.x()); int y_offset = int(XFixedToDouble(tessellator->traps[i].left.p1.y) - bg_origin.y()); XRenderCompositeTrapezoids(dpy, composition_mode, src, picture, antialias ? XRenderFindStandardFormat(dpy, PictStandardA8) : 0, x_offset, y_offset, tessellator->traps + i, 1); } } else { int mask_w = br.width() + (br.x() > 0 ? br.x() : 0); int mask_h = br.height() + (br.y() > 0 ? br.y() : 0); Pixmap mask = XCreatePixmap (dpy, RootWindow(dpy, scrn), mask_w, mask_h, antialias ? 8 : 1); Picture mask_picture = XRenderCreatePicture (dpy, mask, antialias ? XRenderFindStandardFormat(dpy, PictStandardA8) : XRenderFindStandardFormat(dpy, PictStandardA1), CPPolyEdge, &attrs); XRenderColor transparent; transparent.red = 0; transparent.green = 0; transparent.blue = 0; transparent.alpha = 0; XRenderFillRectangle(dpy, PictOpSrc, mask_picture, &transparent, 0, 0, mask_w, mask_h); Picture mask_src = X11->getSolidFill(scrn, Qt::white); qt_XRenderCompositeTrapezoids(dpy, PictOpOver, mask_src, mask_picture, antialias ? XRenderFindStandardFormat(dpy, PictStandardA8) : 0, 0, 0, tessellator->traps, tessellator->size); XRenderComposite(dpy, composition_mode, src, mask_picture, picture, qRound(bg_origin.x()), qRound(bg_origin.y()), 0, 0, 0, 0, mask_w, mask_h); XFreePixmap(dpy, mask); XRenderFreePicture(dpy, mask_picture); } } else { qt_XRenderCompositeTrapezoids(dpy, composition_mode, src, picture, antialias ? XRenderFindStandardFormat(dpy, PictStandardA8) : 0, 0, 0, tessellator->traps, tessellator->size); } tessellator->done(); } } else#endif if (fill.style() != Qt::NoBrush) { if (clippedCount > 0) { QVarLengthArray<XPoint> xpoints(clippedCount); for (int i = 0; i < clippedCount; ++i) { xpoints[i].x = qFloor(clippedPoints[i].x); xpoints[i].y = qFloor(clippedPoints[i].y); } if (mode == QPaintEngine::WindingMode) XSetFillRule(dpy, fill_gc, WindingRule); setupAdaptedOrigin(QPoint(xpoints[0].x, xpoints[0].y)); XFillPolygon(dpy, hd, fill_gc, xpoints.data(), clippedCount, mode == QPaintEngine::ConvexMode ? Convex : Complex, CoordModeOrigin); resetAdaptedOrigin(); if (mode == QPaintEngine::WindingMode) XSetFillRule(dpy, fill_gc, EvenOddRule); } }}void QX11PaintEnginePrivate::strokePolygon_translated(const QPointF *polygonPoints, int pointCount, bool close){ QVarLengthArray<QPointF> translated_points(pointCount); QPointF offset(matrix.dx(), matrix.dy()); for (int i = 0; i < pointCount; ++i) translated_points[i] = polygonPoints[i] + offset; strokePolygon_dev(translated_points.data(), pointCount, close);}void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int pointCount, bool close){ int clippedCount = 0; qt_float_point *clippedPoints = 0; polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount, &clippedPoints, &clippedCount, close); if (clippedCount > 0) { QVarLengthArray<XPoint> xpoints(clippedCount); for (int i = 0; i < clippedCount; ++i) { xpoints[i].x = qFloor(clippedPoints[i].x); xpoints[i].y = qFloor(clippedPoints[i].y); } uint numberPoints = qMin(clippedCount, xlibMaxLinePoints); XPoint *pts = xpoints.data(); XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin); pts += numberPoints; clippedCount -= numberPoints; numberPoints = qMin(clippedCount, xlibMaxLinePoints-1); while (clippedCount) { XDrawLines(dpy, hd, gc, pts-1, numberPoints+1, CoordModeOrigin); pts += numberPoints; clippedCount -= numberPoints; numberPoints = qMin(clippedCount, xlibMaxLinePoints-1); } }}void QX11PaintEngine::drawPolygon(const QPointF *polygonPoints, int pointCount, PolygonDrawMode mode){ Q_D(QX11PaintEngine); if (d->use_path_fallback) { QPainterPath path(polygonPoints[0]); for (int i = 1; i < pointCount; ++i) path.lineTo(polygonPoints[i]); if (mode == PolylineMode) { QBrush oldBrush = d->cbrush; d->cbrush = QBrush(Qt::NoBrush); path.setFillRule(Qt::WindingFill); drawPath(path); d->cbrush = oldBrush; } else { path.setFillRule(mode == OddEvenMode ? Qt::OddEvenFill : Qt::WindingFill); path.closeSubpath(); drawPath(path); } return; } if (mode != PolylineMode && d->has_brush) d->fillPolygon_translated(polygonPoints, pointCount, QX11PaintEnginePrivate::BrushGC, mode); if (d->has_pen) d->strokePolygon_translated(polygonPoints, pointCount, mode != PolylineMode);}void QX11PaintEnginePrivate::fillPath(const QPainterPath &path, QX11PaintEnginePrivate::GCMode gc_mode, bool transform){ QList<QPolygonF> polys = path.toFillPolygons(transform ? matrix : QTransform()); for (int i = 0; i < polys.size(); ++i) { fillPolygon_dev(polys.at(i).data(), polys.at(i).size(), gc_mode, path.fillRule() == Qt::OddEvenFill ? QPaintEngine::OddEvenMode : QPaintEngine::WindingMode); }}void QX11PaintEngine::drawPath(const QPainterPath &path){ Q_D(QX11PaintEngine); if (path.isEmpty()) return; QTransform old_matrix = d->matrix; bool adjust_coords = !(d->render_hints & QPainter::Antialiasing) && (d->has_alpha_pen || (d->has_alpha_brush && d->has_pen && !d->has_alpha_pen) || (d->cpen.style() > Qt::SolidLine));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -