📄 qpaintengine_x11.cpp
字号:
if (adjust_coords) { d->matrix = QTransform(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->has_alpha_brush || (d->render_hints & QPainter::Antialiasing))) || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate) || (d->cpen.style() > Qt::SolidLine))) { QPainterPathStroker stroker; if (d->cpen.style() == Qt::CustomDashLine) { stroker.setDashPattern(d->cpen.dashPattern()); stroker.setDashOffset(d->cpen.dashOffset()); } 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 (d->cpen.isCosmetic()) { stroker.setWidth(width == 0 ? 1 : width); 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::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags){ Q_D(QX11PaintEngine); if (!image.hasAlphaChannel() && d->pdev_depth >= 24 && image.depth() == 32 && r.size() == sr.size()) { int sx = qRound(sr.x()); int sy = qRound(sr.y()); int x = qRound(r.x()); int y = qRound(r.y()); int w = qRound(r.width()); int h = qRound(r.height()); XImage *xi; QImage im(image); // Note: this code assumes either RGB or BGR, 8 bpc server layouts const uint red_mask = (uint) ((Visual *) d->xinfo->visual())->red_mask; bool bgr_layout = (red_mask == 0xff); if ((QSysInfo::ByteOrder == QSysInfo::BigEndian && ((ImageByteOrder(d->dpy) == LSBFirst) || bgr_layout)) || (ImageByteOrder(d->dpy) == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) { for (int i=0; i < im.height(); i++) { uint *p = (uint*)im.scanLine(i); uint *end = p + im.width(); if (bgr_layout && ImageByteOrder(d->dpy) == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) { while (p < end) { *p = ((*p << 8) & 0xffffff00) | ((*p >> 24) & 0x000000ff); p++; } } else if ((ImageByteOrder(d->dpy) == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) || (ImageByteOrder(d->dpy) == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) { while (p < end) { *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); p++; } } else if (ImageByteOrder(d->dpy) == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) { while (p < end) { *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff) | ((*p ) & 0xff00ff00); p++; } } } } xi = XCreateImage(d->dpy, (Visual *) d->xinfo->visual(), d->pdev_depth, ZPixmap, 0, (char *) im.scanLine(sy)+sx*sizeof(uint), w, h, 32, im.bytesPerLine()); XPutImage(d->dpy, d->hd, d->gc, xi, 0, 0, x, y, w, h); xi->data = 0; // QImage owns these bits XDestroyImage(xi); } else { QPaintEngine::drawImage(r, image, sr, flags); }}void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &_sr){ Q_D(QX11PaintEngine); QRectF sr = _sr; 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());#ifndef QT_NO_XRENDER ::Picture src_pict = pixmap.data->picture; if (src_pict && d->picture) { if (pixmap.data->d == 1 && (d->has_alpha_pen)) { qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture, sx, sy, x, y, sw, sh, d->cpen); 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); } else if (d->has_clipping) { XSetClipRectangles(d->dpy, cgc, 0, 0, 0, 0, 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->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, sx, sy, 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 - sx, y - sy); } if (mono_dst) { XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1); } else { QColormap cmap = QColormap::instance(d->scrn); 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 QPixmap *px = static_cast<const QPixmap*>(d->pdev); Pixmap src_mask = pixmap.data->x11_mask; Pixmap dst_mask = px->data->x11_mask; if (dst_mask) { GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0); if (src_mask) { // copy src mask into dst mask XCopyArea(d->dpy, pixmap.data->x11_mask, px->data->x11_mask, cgc, sx, sy, sw, sh, x, y); } else { // no src mask, but make sure the area copied is opaque in dest XSetBackground(d->dpy, cgc, 0); XSetForeground(d->dpy, cgc, 1); XFillRectangle(d->dpy, px->data->x11_mask, cgc, x, y, sw, sh); } XFreeGC(d->dpy, cgc); } } if (restore_clip) { XSetClipOrigin(d->dpy, d->gc, 0, 0); int num; XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); if (num == 0) XSetClipMask(d->dpy, d->gc, XNone); else XSetClipRectangles(d->dpy, d->gc, 0, 0, rects, num, Unsorted); }}void QX11PaintEngine::updateMatrix(const QTransform &mtx){ Q_D(QX11PaintEngine); d->matrix = mtx; d->txop = d->matrix.type(); d->has_complex_xform = (d->txop > QTransform::TxTranslate);}/* NB! the clip region is expected to be in dev coordinates*/void QX11PaintEngine::updateClipRegion_dev(const QRegion &clipRegion, Qt::ClipOperation op){ Q_D(QX11PaintEngine); QRegion sysClip = systemClip(); if (op == Qt::NoClip) { d->has_clipping = false; d->crgn = sysClip; if (!sysClip.isEmpty()) { x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, sysClip); } else { x11ClearClipRegion(d->dpy, d->gc, d->gc_brush, d->picture); } return; } switch (op) { case Qt::IntersectClip: if (d->has_clipping) { d->crgn &= clipRegion; break; } // fall through case Qt::ReplaceClip: if (!sysClip.isEmpty()) d->crgn = clipRegion.intersected(sysClip); else d->crgn = clipRegion; break; case Qt::UniteClip: d->crgn |= clipRegion; if (!sysClip.isEmpty()) d->crgn = d->crgn.intersected(sysClip); break; default: break; } d->has_clipping = true; x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, d->crgn);}void QX11PaintEngine::updateFont(const QFont &){}Qt::HANDLE QX11PaintEngine::handle() const{ Q_D(const QX11PaintEngine); Q_ASSERT(isActive()); Q_ASSERT(d->hd); return d->hd;}extern void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &, qreal, qreal);void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &p){ int x = qRound(r.x()); int y = qRound(r.y()); int w = qRound(r.width()); int h = qRound(r.height()); int sx = qRound(p.x()); int sy = qRound(p.y()); bool mono_src = pixmap.depth() == 1; Q_D(QX11PaintEngine);#ifndef QT_NO_XRENDER if (X11->use_xrender && d->picture && pixmap.x11PictureHandle()) {#if 0 // ### enable this in Qt 5 XRenderPictureAttributes attrs; attrs.repeat = true; XRenderChangePicture(d->dpy, pixmap.x11PictureHandle(), CPRepeat, &attrs); if (mono_src) { qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture, sx, sy, x, y, w, h, d->cpen); } else { XRenderComposite(d->dpy, d->composition_mode, pixmap.x11PictureHandle(), XNone, d->picture, sx, sy, 0, 0, x, y, w, h); }#else const int numTiles = (w / pixmap.width()) * (h / pixmap.height()); if (numTiles < 100) { // this is essentially qt_draw_tile(), inlined for // the XRenderComposite call int yPos, xPos, drawH, drawW, yOff, xOff; yPos = y; yOff = sy; while(yPos < y + h) { drawH = pixmap.height() - yOff; // Cropping first row if (yPos + drawH > y + h) // Cropping last row drawH = y + h - yPos; xPos = x; xOff = sx; while(xPos < x + w) { drawW = pixmap.width() - xOff; // Cropping first column if (xPos + drawW > x + w) // Cropping last column drawW = x + w - xPos; if (mono_src) { qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture, xOff, yOff, xPos, yPos, drawW, drawH, d->cpen); } else { XRenderComposite(d->dpy, d->composition_mode, pixmap.x11PictureHandle(), XNone, d->picture, xOff, yOff, 0, 0, xPos, yPos, drawW, drawH); } xPos += drawW; xOff = 0; } yPos += drawH; yOff = 0; } } else { w = qMin(w, d->pdev->width() - x); h = qMin(h, d->pdev->height() - y); const int pw = w + sx; const int ph = h + sy; QPixmap pm(pw, ph); if (pixmap.hasAlpha() || mono_src) pm.fill(Qt::transparent); const int mode = pix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -