📄 qpixmap_x11.cpp
字号:
/*! Detaches the pixmap from shared pixmap data. A pixmap is automatically detached by Qt whenever its contents are about to change. This is done in almost all QPixmap member functions that modify the pixmap (fill(), convertFromImage(), load(), etc.), and in QPainter::begin() on a pixmap. There are two exceptions in which detach() must be called explicitly, that is when calling the handle() or the x11PictureHandle() function (only available on X11). Otherwise, any modifications done using system calls, will be performed on the shared data. The detach() function returns immediately if there is just a single reference or if the pixmap has not been initialized yet.*/void QPixmap::detach(){ ++data->detach_no; if (data->count != 1) *this = copy(); data->uninit = false; // reset the cache data if (data->hd2) { XFreePixmap(X11->display, data->hd2); data->hd2 = 0; }}/*! Returns the default pixmap depth used by the application. \sa depth(), {QPixmap#Pixmap Information}{Pixmap Information}*/int QPixmap::defaultDepth(){ return QX11Info::appDepth();}/*! Fills the pixmap with the given \a fillColor. \sa {QPixmap#Pixmap Transformations}{Pixmap Transformations}*/void QPixmap::fill(const QColor &fillColor){ if (isNull()) return; if (fillColor.alpha() != 255) {#ifndef QT_NO_XRENDER if (data->picture && data->d == 32) { ::Picture src = X11->getSolidFill(data->xinfo.screen(), fillColor); XRenderComposite(X11->display, PictOpSrc, src, 0, data->hd, 0, 0, width(), height(), 0, 0, width(), height()); } else#endif { QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied); im.fill(PREMUL(fillColor.rgba())); *this = QPixmap::fromImage(im); } return; } else { detach(); } GC gc = XCreateGC(X11->display, data->hd, 0, 0); if (depth() == 1) { XSetForeground(X11->display, gc, qGray(fillColor.rgb()) > 127 ? 0 : 1); } else if (X11->use_xrender && data->d >= 24) { XSetForeground(X11->display, gc, fillColor.rgba()); } else { XSetForeground(X11->display, gc, QColormap::instance(data->xinfo.screen()).pixel(fillColor)); } XFillRectangle(X11->display, data->hd, gc, 0, 0, width(), height()); XFreeGC(X11->display, gc);}/*! Returns the alpha channel of the pixmap. If the pixmap doesn't have an alpha channel (i.e. the alpha channel's value equals 0xff), a null pixmap is returned. \sa setAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap Information}*/QPixmap QPixmap::alphaChannel() const{ if (!hasAlphaChannel()) return QPixmap(); QImage im(toImage()); return fromImage(im.alphaChannel(), Qt::OrderedDither);}/*! \fn void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) Sets the alpha channel of this pixmap to the given \a alphaChannel by converting the \a alphaChannel into 32 bit and using the intensity of the RGB pixel values. \sa alphaChannel(), {QPixmap#Pixmap Transformations}{Pixmap Transformations} */void QPixmap::setAlphaChannel(const QPixmap &alpha){ if (alpha.isNull()) return; if (width() != alpha.width() && height() != alpha.height()) { qWarning("QPixmap::setAlphaChannel: The pixmap and the alpha channel pixmap must have the same size"); return; } QImage im(toImage()); im.setAlphaChannel(alpha.toImage()); *this = fromImage(im, Qt::OrderedDither | Qt::OrderedAlphaDither);}/*! \fn QBitmap QPixmap::mask() const Returns the mask, or a null bitmap if no mask has been set. \sa setMask(), {QPixmap#Pixmap Information}{Pixmap Information}*/QBitmap QPixmap::mask() const{ QBitmap mask;#ifndef QT_NO_XRENDER if (data->picture && data->d == 32) { // #### slow - there must be a better way.. mask = QBitmap::fromImage(toImage().createAlphaMask()); } else#endif if (depth() == 1) { mask = *this; } else { mask = data->mask_to_bitmap(); } return mask;}/*! Sets a mask bitmap. The \a newmask bitmap defines the clip mask for this pixmap. Every pixel in \a newmask corresponds to a pixel in this pixmap. Pixel value 1 means opaque and pixel value 0 means transparent. The mask must have the same size as this pixmap. \warning Setting the mask on a pixmap will cause any alpha channel data to be cleared. For example: \quotefromfile snippets/image/image.cpp \skipto MASK \skipto QPixmap \printuntil setMask Now, alpha and alphacopy are visually different. Setting a null mask resets the mask. \sa mask(), {QPixmap#Pixmap Transformations}{Pixmap Transformations}, QBitmap*/void QPixmap::setMask(const QBitmap &newmask){ if (data == newmask.data) // trying to selfmask return; if (newmask.isNull()) { // clear mask#ifndef QT_NO_XRENDER if (data->picture && data->d == 32) { QPixmap pixmap; if (data->type == QPixmap::BitmapType) pixmap = QBitmap(data->w, data->h); else pixmap = QPixmap(data->w, data->h); pixmap.fill(Qt::black); XRenderComposite(X11->display, PictOpOver, data->picture, 0, pixmap.data->picture, 0, 0, 0, 0, 0, 0, data->w, data->h); *this = pixmap; } else#endif if (data->x11_mask) {#ifndef QT_NO_XRENDER if (data->picture) { XRenderPictureAttributes attrs; attrs.alpha_map = 0; XRenderChangePicture(X11->display, data->picture, CPAlphaMap, &attrs); } if (data->mask_picture) XRenderFreePicture(X11->display, data->mask_picture); data->mask_picture = 0;#endif XFreePixmap(X11->display, data->x11_mask); data->x11_mask = 0; } return; } if (newmask.width() != width() || newmask.height() != height()) { qWarning("QPixmap::setMask: The pixmap and the mask must have the same size"); return; } detach();#ifndef QT_NO_XRENDER if (data->picture && data->d == 32) { XRenderComposite(X11->display, PictOpSrc, data->picture, newmask.x11PictureHandle(), data->picture, 0, 0, 0, 0, 0, 0, data->w, data->h); } else#endif if (depth() == 1) { XGCValues vals; vals.function = GXand; GC gc = XCreateGC(X11->display, data->hd, GCFunction, &vals); XCopyArea(X11->display, newmask.handle(), data->hd, gc, 0, 0, width(), height(), 0, 0); XFreeGC(X11->display, gc); } else { // ##### should or the masks together if (data->x11_mask) { XFreePixmap(X11->display, data->x11_mask);#ifndef QT_NO_XRENDER if (data->mask_picture) XRenderFreePicture(X11->display, data->mask_picture);#endif } data->x11_mask = QPixmapData::bitmap_to_mask(newmask, data->xinfo.screen());#ifndef QT_NO_XRENDER if (data->picture) { data->mask_picture = XRenderCreatePicture(X11->display, data->x11_mask, XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0); XRenderPictureAttributes attrs; attrs.alpha_map = data->mask_picture; XRenderChangePicture(X11->display, data->picture, CPAlphaMap, &attrs); }#endif }}/*! \reimp*/int QPixmap::metric(PaintDeviceMetric m) const{ int val; if (m == PdmWidth) val = width(); else if (m == PdmHeight) { val = height(); } else { Display *dpy = X11->display; int scr = data->xinfo.screen(); switch (m) { case PdmDpiX: case PdmPhysicalDpiX: val = QX11Info::appDpiX(scr); break; case PdmDpiY: case PdmPhysicalDpiY: val = QX11Info::appDpiY(scr); break; case PdmWidthMM: val = (DisplayWidthMM(dpy,scr)*width())/ DisplayWidth(dpy,scr); break; case PdmHeightMM: val = (DisplayHeightMM(dpy,scr)*height())/ DisplayHeight(dpy,scr); break; case PdmNumColors: val = 1 << depth(); break; case PdmDepth: val = depth(); break; default: val = 0; qWarning("QPixmap::metric: Invalid metric command"); } } return val;}/*! Converts the pixmap to a QImage. Returns a null image if the conversion fails. If the pixmap has 1-bit depth, the returned image will also be 1 bit deep. If the pixmap has 2- to 8-bit depth, the returned image has 8-bit depth. If the pixmap has greater than 8-bit depth, the returned image has 32-bit depth. Note that for the moment, alpha masks on monochrome images are ignored. \sa convertFromImage(), {QImage#Image Formats}{Image Formats}*/QImage QPixmap::toImage() const{ if (isNull()) return QImage(); // null image int w = width(); int h = height(); int d = depth(); Visual *visual = (Visual *) data->xinfo.visual(); bool trucol = (visual->c_class >= TrueColor) && d > 8; QImage::Format format = QImage::Format_Mono; if (d > 1 && d <= 8) { d = 8; format = QImage::Format_Indexed8; } // we could run into the situation where d == 8 AND trucol is true, which can // cause problems when converting to and from images. in this case, always treat // the depth as 32... if (d > 8 || trucol) { d = 32; format = QImage::Format_RGB32; } XImage *xi = XGetImage(X11->display, data->hd, 0, 0, w, h, AllPlanes, (d == 1) ? XYPixmap : ZPixmap); Q_CHECK_PTR(xi); if (!xi) return QImage(); if (data->picture && data->d == 32) { QImage image(data->w, data->h, QImage::Format_ARGB32_Premultiplied); memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height); // throw away image data qSafeXDestroyImage(xi); return image; } if (d == 1 && xi->bitmap_bit_order == LSBFirst) format = QImage::Format_MonoLSB; if (data->x11_mask && format == QImage::Format_RGB32) format = QImage::Format_ARGB32; QImage image(w, h, format); if (image.isNull()) // could not create image return image; QImage alpha; if (data->x11_mask) { alpha = mask().toImage(); } bool ale = alpha.format() == QImage::Format_MonoLSB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -