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 "needletrail.h" #include <qul/image.h> #include <qul/private/texture.h> #include <qul/private/rasterbuffer.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> Qul::PlatformInterface::Rect NeedleTrailDelegate::boundingRect(Qul::PlatformInterface::Size size) const { return Qul::PlatformInterface::Rect(0, 0, size.width(), size.height()); } Qul::PlatformInterface::Transform computeRotationTransform(float cx, float cy, float w, float h, float angle, bool flip) { Qul::PlatformInterface::Transform transform; transform.translate(0, -h * 0.5f); if (flip) transform.scale(-1, 1); transform.rotate(angle); transform.translate(w * 0.5f, h * 0.5f); transform.translate(cx, cy); return transform; } void NeedleTrailDelegate::rotationChanged() { const float angle = rotation.value(); if (m_initialized) { m_trailAngle += 0.02 * (angle - m_trailAngle); } else { m_trailAngle = angle; } update(); } void NeedleTrailDelegate::paint(Qul::PlatformInterface::DrawingDevice *device, const Qul::PlatformInterface::Rect &clip, const Qul::PlatformInterface::Transform &offset, Qul::PlatformInterface::Size size, float opacity) const { const float angle = rotation.value(); if (!m_initialized) { #ifdef QUL_TVIIC_PLATFORM if (mask.value().textureCount() != 1) { Qul::PlatformInterface::log("TVII effects: needle trail: Unexpected texture count %i\r\n", mask.value().textureCount()); std::terminate(); } auto texture = mask.value().texture(); CyGfx::loadSurface(&m_trailMask, texture); #endif m_trailAngle = angle; m_initialized = true; } float angleDelta = std::min(1.0f, 0.025f * std::abs(angle - m_trailAngle)); float s = 1.0 - angleDelta; float steepness = 1.5; // HW supports no more than 3.99 float maxAlpha = 0.8; float is = steepness * s; float ss = maxAlpha + (steepness - maxAlpha) * s; auto transform = computeRotationTransform(offset.dx(), offset.dy(), size.width(), size.height(), angle, m_trailAngle < angle); #ifdef QUL_TVIIC_PLATFORM void **platformContext = static_cast<void **>(device->platformContext()); CYGFX_BE_CONTEXT ctx = static_cast<CYGFX_BE_CONTEXT>(platformContext[0]); CYGFX_ERROR ret = CYGFX_OK; float colorMatrix[5][4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0.8, 0.8, ss * opacity}, {0, 0, 0, -is * opacity}, }; Mat3x3 matrix{transform.m11(), transform.m12(), transform.m13(), transform.m21(), transform.m22(), transform.m23(), transform.dx(), transform.dy(), transform.m33()}; UTIL_SUCCESS(ret, CyGfx_CmSetColorMatrix(ctx, CYGFX_CM_CMATRIX_FORMAT_5X4, &colorMatrix[0][0])); 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())); } UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, m_trailMask)); 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_CmSetColorMatrix(ctx, CYGFX_CM_CMATRIX_FORMAT_4X3, nullptr)); 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()); QVector<QRgb> colorTable(256); for (int i = 0; i < 256; ++i) { int gb = qRound(0.8 * i); int alpha = qBound(0, qRound(ss * i - is * 255), 255); colorTable[i] = qRgba(0, gb, gb, alpha); } if (mask.value().textureCount() != 1) { Qul::PlatformInterface::log("TVII effects: needle trail: Unexpected texture count %i\r\n", mask.value().textureCount()); std::terminate(); } auto texture = mask.value().texture(); assert(texture.bitsPerPixel() == 8); QImage image(texture.data(), texture.width(), texture.height(), texture.bytesPerLine(), QImage::Format_Indexed8); image.setColorTable(colorTable); 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(), image); p->restore(); #endif }