📄 qpaintengine_x11.cpp
字号:
QPaintEngine::PolygonDrawMode mode){ int clippedCount = 0; qt_float_point *clippedPoints = 0; //can change if we switch to pen if gcMode != BrushGC bool has_fill_texture = has_texture; bool has_fill_pattern = has_pattern;#ifndef QT_NO_XRENDER ::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, bg_brush, bg_mode == Qt::OpaqueMode); else src = X11->getSolidFill(scrn, fill.color());#endif } polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount, &clippedPoints, &clippedCount);#if !defined(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 || antialias || !solid_fill || has_alpha_pen != has_alpha_brush)) { QVector<XTrapezoid> traps; traps.reserve(128); QRect br; qt_tesselate_polygon(&traps, (QPointF *)clippedPoints, clippedCount, mode == QPaintEngine::WindingMode, &br); if (traps.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 < traps.size(); ++i) { int x_offset = int(XFixedToDouble(traps.at(i).left.p1.x) - bg_origin.x()); int y_offset = int(XFixedToDouble(traps.at(i).left.p1.y) - bg_origin.y()); XRenderCompositeTrapezoids(dpy, composition_mode, src, picture, antialias ? XRenderFindStandardFormat(dpy, PictStandardA8) : 0, x_offset, y_offset, traps.constData() + 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, traps); 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, traps); } } } 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 : QMatrix()); 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; bool adjust_coords = d->has_alpha_pen && !(d->render_hints & QPainter::Antialiasing); QMatrix old_matrix = d->matrix; if (adjust_coords) { d->matrix = QMatrix(d->matrix.m11(), d->matrix.m12(), d->matrix.m21(), d->matrix.m22(), d->matrix.dx() + 0.5f, d->matrix.dy() + 0.5f); } if (d->has_brush) d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true); if (d->has_pen && ((X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing))) || (d->cpen.widthF() > 0 && d->txop > QPainterPrivate::TxTranslate) || (d->cpen.style() > Qt::SolidLine))) { QPainterPathStroker stroker; if (d->cpen.style() == Qt::CustomDashLine) stroker.setDashPattern(d->cpen.dashPattern()); else stroker.setDashPattern(d->cpen.style()); stroker.setCapStyle(d->cpen.capStyle()); stroker.setJoinStyle(d->cpen.joinStyle()); QPainterPath stroke; qreal width = d->cpen.widthF(); QPolygonF poly; // necessary to get aliased alphablended primitives to be drawn correctly if (width == 0) { stroker.setWidth(1); stroke = stroker.createStroke(path * d->matrix); if (stroke.isEmpty()) return; stroke.setFillRule(Qt::WindingFill); d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false); } else { stroker.setWidth(width); stroke = stroker.createStroke(path); if (stroke.isEmpty()) return; stroke.setFillRule(Qt::WindingFill); d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, true); } } else if (d->has_pen) { // if we have a pen width of 0 - use XDrawLine() for speed QList<QPolygonF> polys = path.toSubpathPolygons(d->matrix); for (int i = 0; i < polys.size(); ++i) d->strokePolygon_dev(polys.at(i).data(), polys.at(i).size(), false); } if (adjust_coords) d->matrix = old_matrix;}void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &_sr){ Q_D(QX11PaintEngine); QRectF sr = _sr; if (r.size() != sr.size()) { QImage image = pixmap.toImage(); image = image.copy(sr.toRect()); image = image.scaled(qRound(r.width()), qRound(r.height()), Qt::IgnoreAspectRatio, d->render_hints & QPainter::SmoothPixmapTransform ? Qt::SmoothTransformation : Qt::FastTransformation); sr = QRectF(0, 0, r.width(), r.height()); // this recursive call here prevents us from doing a pixmap assignment, // and thus triggering a deep copy if pixmap is being painted on // Nice trick to speed such things up... drawPixmap(r, QPixmap::fromImage(image), sr); return; } int x = qRound(r.x()); int y = qRound(r.y()); int sx = qRound(sr.x()); int sy = qRound(sr.y()); int sw = qRound(sr.width()); int sh = qRound(sr.height()); if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen()) || (pixmap.x11Info().screen() != DefaultScreen(X11->display))) { QPixmap* p = const_cast<QPixmap *>(&pixmap); p->x11SetScreen(d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display)); } QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen());#if !defined(QT_NO_XRENDER) ::Picture src_pict = pixmap.data->picture; if (src_pict && d->picture) { if (pixmap.data->d == 1 && (d->has_alpha_pen || d->bg_brush != Qt::NoBrush)) { qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture, sx, sy, x, y, sw, sh, d->cpen, d->bg_brush, d->bg_mode == Qt::OpaqueMode); return; } else if (pixmap.data->d != 1 && (pixmap.data->d == 32 || pixmap.data->d != d->pdev_depth)) { XRenderComposite(d->dpy, d->composition_mode, src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh); return; } }#endif bool mono_src = pixmap.data->d == 1; bool mono_dst = d->pdev_depth == 1; bool restore_clip = false; if (pixmap.data->x11_mask) { // pixmap has a mask QBitmap comb(sw, sh); GC cgc = XCreateGC(d->dpy, comb.handle(), 0, 0); XSetForeground(d->dpy, cgc, 0); XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh); XSetBackground(d->dpy, cgc, 0); XSetForeground(d->dpy, cgc, 1); if (!d->crgn.isEmpty()) { int num; XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted); } XSetFillStyle(d->dpy, cgc, FillOpaqueStippled); XSetTSOrigin(d->dpy, cgc, -sx, -sy); XSetStipple(d->dpy, cgc, pixmap.data->x11_mask); XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh); XFreeGC(d->dpy, cgc); XSetClipOrigin(d->dpy, d->gc, x, y); XSetClipMask(d->dpy, d->gc, comb.handle()); restore_clip = true; } if (mono_src) { if (d->bg_mode == Qt::OpaqueMode) { if (mono_dst) XSetForeground(d->dpy, d->gc, qGray(d->bg_brush.color().rgb()) > 127 ? 0 : 1); else XSetForeground(d->dpy, d->gc, QColormap::instance(d->scrn).pixel(d->bg_brush.color())); XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh); } if (!d->crgn.isEmpty()) { Pixmap comb = XCreatePixmap(d->dpy, d->hd, sw, sh, 1); GC cgc = XCreateGC(d->dpy, comb, 0, 0); XSetForeground(d->dpy, cgc, 0); XFillRectangle(d->dpy, comb, cgc, 0, 0, sw, sh); int num; XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted); XCopyArea(d->dpy, pixmap.handle(), comb, cgc, 0, 0, sw, sh, 0, 0); XFreeGC(d->dpy, cgc); XSetClipMask(d->dpy, d->gc, comb); XSetClipOrigin(d->dpy, d->gc, x, y); XFreePixmap(d->dpy, comb); } else { XSetClipMask(d->dpy, d->gc, pixmap.handle()); XSetClipOrigin(d->dpy, d->gc, x, y); } if (mono_dst) { XSetBackground(d->dpy, d->gc, qGray(d->bg_brush.color().rgb()) > 127 ? 0 : 1); XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1); } else { QColormap cmap = QColormap::instance(d->scrn); XSetBackground(d->dpy, d->gc, cmap.pixel(d->bg_brush.color())); XSetForeground(d->dpy, d->gc, cmap.pixel(d->cpen.color())); } XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh); restore_clip = true; } else { XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y); } if (d->pdev->devType() == QInternal::Pixmap) { const QPixma
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -