QImage::Format QVGPixmapData::idealFormat(QImage *image, Qt::ImageConversionFlags flags) const { QImage::Format format = sourceFormat(); int d = image->depth(); if (d == 1 || d == 16 || d == 24 || (d == 32 && !image->hasAlphaChannel())) format = QImage::Format_RGB32; else if (!(flags & Qt::NoOpaqueDetection) && image->data_ptr()->checkForAlphaPixels()) format = sourceFormat(); else format = image->hasAlphaChannel() ? sourceFormat() : QImage::Format_RGB32; return format; }
void QVGPixmapData::ensureReadback(bool readOnly) const { if (vgImage != VG_INVALID_HANDLE && source.isNull()) { source = QVolatileImage(w, h, sourceFormat()); source.beginDataAccess(); vgGetImageSubData(vgImage, source.bits(), source.bytesPerLine(), qt_vg_image_to_vg_format(source.format()), 0, 0, w, h); source.endDataAccess(); if (readOnly) { recreate = false; } else { // Once we did a readback, the original VGImage must be destroyed // because it may be shared (e.g. created via SgImage) and a subsequent // upload of the image data may produce unexpected results. const_cast<QVGPixmapData *>(this)->destroyImages(); #if defined(Q_OS_SYMBIAN) // There is now an own copy of the data so drop the handle provider, // otherwise toVGImage() would request the handle again, which is wrong. nativeImageHandleProvider = 0; #endif recreate = true; } } }
// Force the pixmap data to be in QImage format. void QVGPixmapData::forceToImage() { if (!isValid()) return; if (source.isNull()) source = QImage(w, h, sourceFormat()); recreate = true; }
void QVGPixmapData::fromImage (const QImage &image, Qt::ImageConversionFlags flags) { if (image.size() == QSize(w, h)) setSerialNumber(++qt_vg_pixmap_serial); else resize(image.width(), image.height()); source = image.convertToFormat(sourceFormat(), flags); recreate = true; }
QImage QVGPixmapData::toImage() const { if (!isValid()) return QImage(); ensureReadback(true); if (source.isNull()) { source = QVolatileImage(w, h, sourceFormat()); recreate = true; } return source.toImage(); }
QImage QVGPixmapData::toImage() const { if (!isValid()) return QImage(); if (source.isNull()) { source = QImage(w, h, sourceFormat()); recreate = true; } return source; }
// Ensures that the pixmap is backed by some valid data and forces the data to // be re-uploaded to the VGImage when toVGImage() is called next time. void QVGPixmapData::forceToImage(bool allowReadback) { if (!isValid()) return; if (allowReadback) ensureReadback(false); if (source.isNull()) source = QVolatileImage(w, h, sourceFormat()); recreate = true; }
void QVGPixmapData::fill(const QColor &color) { if (!isValid()) return; if (source.isNull()) source = QImage(w, h, sourceFormat()); if (source.depth() == 1) { // Pick the best approximate color in the image's colortable. int gray = qGray(color.rgba()); if (qAbs(qGray(source.color(0)) - gray) < qAbs(qGray(source.color(1)) - gray)) source.fill(0); else source.fill(1); } else { source.fill(PREMUL(color.rgba())); } // Re-upload the image to VG the next time toVGImage() is called. recreate = true; }
void* QVGPixmapData::toNativeType(NativeType type) { if (type == QPixmapData::SgImage) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) toVGImage(); if (!isValid() || vgImage == VG_INVALID_HANDLE) return 0; TInt err = 0; RSgDriver driver; err = driver.Open(); if (err != KErrNone) return 0; TSgImageInfo sgInfo; sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE; sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; QScopedPointer<RSgImage> sgImage(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); return 0; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage.data(), (EGLint*)KEglImageAttribs); if (!eglImage || eglGetError() != EGL_SUCCESS) { sgImage->Close(); driver.Close(); return 0; } VGImage dstVgImage = QVG::vgCreateEGLImageTargetKHR(eglImage); if (!dstVgImage || vgGetError() != VG_NO_ERROR) { QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); sgImage->Close(); driver.Close(); return 0; } vgCopyImage(dstVgImage, 0, 0, vgImage, 0, 0, w, h, VG_FALSE); if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); sgImage.reset(); } // release stuff vgDestroyImage(dstVgImage); QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return reinterpret_cast<void*>(sgImage.take()); #endif } else if (type == QPixmapData::FbsBitmap && isValid()) { ensureReadback(true); if (source.isNull()) { source = QVolatileImage(w, h, sourceFormat()); } // Just duplicate the bitmap handle, no data copying happens. return source.duplicateNativeImage(); } return 0; }