C
Qt Quick Ultralite tvii_effects Example
/****************************************************************************** ** ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/#include "imagewithopacitymask.h" #include <qul/image.h> #include <platform/platform.h> #include <qul/private/texture.h> #include <qul/private/rasterbuffer.h> #include <platforminterface/log.h> #include <cstring> #include <memory> #ifdef QUL_TVIIC_PLATFORM #include <sm_util.h> #include <pe_matrix.h> #include "cygfx.h" #else #include <QImage> #include <QPainter> #include <QVector> #include "desktop.h" #endif #include <qul/private/unicodestring.h> #include <qul/private/image_p.h> #include <platforminterface/log.h> Qul::PlatformInterface::Rect ImageWithOpacityMaskDelegate::boundingRect(Qul::PlatformInterface::Size) const { if (source.value().textureCount() != 1) { Qul::PlatformInterface::log("TVII effects: image with opacity mask: Unexpected texture count %i\r\n", source.value().textureCount()); std::terminate(); } auto texture = source.value().texture(); return Qul::PlatformInterface::Rect(0, 0, texture.width(), texture.height()); } void ImageWithOpacityMaskDelegate::paint(Qul::PlatformInterface::DrawingDevice *device, const Qul::PlatformInterface::Rect &clip, const Qul::PlatformInterface::Transform &transform, Qul::PlatformInterface::Size, float opacity) const { if (source.value().textureCount() != 1) { Qul::PlatformInterface::log("TVII effects: image with opacity mask: Unexpected texture count %i\r\n", source.value().textureCount()); std::terminate(); } auto texture = source.value().texture(); if (mask.value().textureCount() != 1) { Qul::PlatformInterface::log("TVII effects: image with opacity mask: Unexpected texture count %i\r\n", mask.value().textureCount()); std::terminate(); } auto maskTexture = mask.value().texture(); if (!m_initialized) { #ifdef QUL_TVIIC_PLATFORM CyGfx::loadSurface(&m_source, texture); CyGfx::loadSurface(&m_mask, maskTexture); #endif m_initialized = true; } #ifdef QUL_TVIIC_PLATFORM void **platformContext = static_cast<void **>(device->platformContext()); CYGFX_BE_CONTEXT ctx = static_cast<CYGFX_BE_CONTEXT>(platformContext[0]); CYGFX_SURFACE surface = static_cast<CYGFX_SURFACE>(platformContext[1]); CYGFX_ERROR ret = CYGFX_OK; CYGFX_U32 renderMode; UTIL_SUCCESS(ret, CyGfx_BeGetAttribute(ctx, CYGFX_BE_CTX_ATTR_RENDER_MODE, &renderMode)); if (renderMode == CYGFX_BE_RENDER_MODE_IBO) { Qul::PlatformInterface::log("ImageWithOpacityMaskDelegate doesn't support IBO layers\n"); return; } Mat3x3 matrix{transform.m11(), transform.m12(), transform.m13(), transform.m21(), transform.m22(), transform.m23(), transform.dx(), transform.dy(), transform.m33()}; bool hasClipping = false; if (clip != Qul::PlatformInterface::Rect(0, 0, device->width(), device->height())) { // Blend only in clip area UTIL_SUCCESS(ret, CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_STORE, CYGFX_BE_SURF_ATTR_USE_CLIPPING, CYGFX_TRUE)); UTIL_SUCCESS(ret, CyGfx_BeActiveArea(ctx, CYGFX_BE_TARGET_STORE, clip.x(), clip.y(), clip.width(), clip.height())); } CYGFX_SURFACE transformedMask = CYGFX_BE_SURF_MASK_ALPHA; UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, m_mask)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_STORE, transformedMask)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_DST, 0)); UTIL_SUCCESS(ret, CyGfx_BeSetGeoMatrix(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_GEO_MATRIX_FORMAT_3X3, matrix)); UTIL_SUCCESS(ret, CyGfx_BeBlt(ctx, 0, 0)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_STORE | CYGFX_BE_TARGET_DST, surface)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, m_source)); if (opacity != 1) { UTIL_SUCCESS(ret, CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_SURF_ATTR_COLOR, CYGFX_SM_COLOR_TO_RGBA(255, 255, 255, int(255 * opacity)))); UTIL_SUCCESS(ret, CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_SURF_ATTR_ALPHAMULTI, CYGFX_TRUE)); } UTIL_SUCCESS(ret, CyGfx_BeSetGeoMatrix(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_GEO_MATRIX_FORMAT_3X3, matrix)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_MASK, transformedMask)); UTIL_SUCCESS(ret, CyGfx_BeBlt(ctx, 0, 0)); UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_MASK, nullptr)); if (hasClipping) UTIL_SUCCESS(ret, CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_STORE, CYGFX_BE_SURF_ATTR_USE_CLIPPING, CYGFX_FALSE)); #else QPainter *p = static_cast<QPainter *>(device->platformContext()); QImage image(texture.data(), texture.width(), texture.height(), texture.bytesPerLine(), toQImageFormat(texture.format())); QImage maskImage(maskTexture.data(), maskTexture.width(), maskTexture.height(), maskTexture.bytesPerLine(), toQImageFormat(maskTexture.format())); QImage withMask = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); QPainter imagePainter(&withMask); imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); imagePainter.drawImage(0, 0, maskImage); imagePainter.end(); p->save(); p->setClipRect(QRect(clip.x(), clip.y(), clip.width(), clip.height())); p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); p->setTransform(toQTransform(transform)); p->setOpacity(opacity); p->drawImage(QPoint(), withMask); p->restore(); #endif }