File indexing completed on 2025-03-09 03:52:07

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-01-19
0007  * Description : a presentation tool.
0008  *
0009  * SPDX-FileCopyrightText:      2004 by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2006-2009 by Valerio Fuoglio <valerio.fuoglio@gmail.com>
0011  * SPDX-FileCopyrightText:      2009 by Andi Clemens <andi dot clemens at googlemail dot com>
0012  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0013  * SPDX-FileCopyrightText:      2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com>
0014  *
0015  * SPDX-License-Identifier: GPL-2.0-or-later
0016  *
0017  * ============================================================ */
0018 
0019 #include "presentationgl.h"
0020 
0021 // C++ includes
0022 
0023 #include <cmath>
0024 #include <cstdlib>
0025 
0026 // Qt includes
0027 
0028 #include <QCursor>
0029 #include <QScreen>
0030 #include <QWindow>
0031 #include <QEvent>
0032 #include <QFileInfo>
0033 #include <QFontMetrics>
0034 #include <QImage>
0035 #include <QPainter>
0036 #include <QPainterPath>
0037 #include <QPainterPathStroker>
0038 #include <QPixmap>
0039 #include <QTimer>
0040 #include <QApplication>
0041 #include <QOpenGLTexture>
0042 
0043 // KDE includes
0044 
0045 #include <klocalizedstring.h>
0046 
0047 // Local includes
0048 
0049 #include "digikam_config.h"
0050 #include "digikam_debug.h"
0051 #include "presentationcontainer.h"
0052 #include "presentationctrlwidget.h"
0053 #include "presentationloader.h"
0054 
0055 // OpenGL headers is not included automatically with ARM targets
0056 
0057 #ifdef Q_PROCESSOR_ARM
0058 #   include <GL/gl.h>
0059 #endif
0060 
0061 #ifdef HAVE_MEDIAPLAYER
0062 #   include "presentationaudiowidget.h"
0063 #endif
0064 
0065 using namespace Digikam;
0066 
0067 namespace DigikamGenericPresentationPlugin
0068 {
0069 
0070 class Q_DECL_HIDDEN PresentationGL::Private
0071 {
0072 
0073 public:
0074 
0075     explicit Private()
0076       : timer           (nullptr),
0077         fileIndex       (0),
0078         imageLoader     (nullptr),
0079         tex1First       (true),
0080         curr            (0),
0081         width           (0),
0082         height          (0),
0083         xMargin         (0),
0084         yMargin         (0),
0085         effect          (nullptr),
0086         effectRunning   (false),
0087         timeout         (0),
0088         random          (false),
0089         endOfShow       (false),
0090         i               (0),
0091         dir             (0),
0092         slideCtrlWidget (nullptr),
0093 
0094 #ifdef HAVE_MEDIAPLAYER
0095 
0096         playbackWidget  (nullptr),
0097 
0098 #endif
0099 
0100         mouseMoveTimer  (nullptr),
0101         deskX           (0),
0102         deskY           (0),
0103         deskWidth       (0),
0104         deskHeight      (0),
0105         sharedData      (nullptr),
0106         randomGenerator (QRandomGenerator::global())
0107     {
0108         texture[0] = nullptr;
0109         texture[1] = nullptr;
0110         texture[2] = nullptr;
0111     }
0112 
0113     QMap<QString, EffectMethod>       effects;
0114 
0115     QTimer*                           timer;
0116     int                               fileIndex;
0117 
0118     PresentationLoader*               imageLoader;
0119     QOpenGLTexture*                   texture[3];
0120     bool                              tex1First;
0121     int                               curr;
0122 
0123     int                               width;
0124     int                               height;
0125     int                               xMargin;
0126     int                               yMargin;
0127 
0128 
0129     EffectMethod                      effect;
0130     bool                              effectRunning;
0131     int                               timeout;
0132     bool                              random;
0133     bool                              endOfShow;
0134 
0135     int                               i;
0136     int                               dir;
0137     float                             points[40][40][3] = { { { 0.0 } } };
0138 
0139     PresentationCtrlWidget*           slideCtrlWidget;
0140 
0141 #ifdef HAVE_MEDIAPLAYER
0142 
0143     PresentationAudioWidget*          playbackWidget;
0144 
0145 #endif
0146 
0147     QTimer*                           mouseMoveTimer;
0148 
0149     int                               deskX;
0150     int                               deskY;
0151     int                               deskWidth;
0152     int                               deskHeight;
0153 
0154     PresentationContainer*            sharedData;
0155 
0156     QRandomGenerator*                 randomGenerator;
0157 };
0158 
0159 PresentationGL::PresentationGL(PresentationContainer* const sharedData)
0160     : QOpenGLWidget(),
0161       d            (new Private)
0162 {
0163     setAttribute(Qt::WA_DeleteOnClose);
0164     setContextMenuPolicy(Qt::PreventContextMenu);
0165 
0166 #ifdef Q_OS_WIN
0167 
0168     setWindowFlags(Qt::Popup               |
0169                    Qt::FramelessWindowHint |
0170                    Qt::WindowStaysOnTopHint);
0171 
0172 #else
0173 
0174     setWindowState(windowState() | Qt::WindowFullScreen);
0175 
0176 #endif
0177 
0178     QScreen* screen = qApp->primaryScreen();
0179 
0180     if (QWidget* const widget = qApp->activeWindow())
0181     {
0182         if (QWindow* const window = widget->windowHandle())
0183         {
0184             screen = window->screen();
0185         }
0186     }
0187 
0188     QRect deskRect = screen->geometry();
0189     d->deskX       = deskRect.x();
0190     d->deskY       = deskRect.y();
0191     d->deskWidth   = deskRect.width();
0192     d->deskHeight  = deskRect.height();
0193 
0194     move(d->deskX, d->deskY);
0195     resize(d->deskWidth, d->deskHeight);
0196 
0197     d->sharedData          = sharedData;
0198     d->sharedData->display = this;
0199 
0200     d->slideCtrlWidget     = new PresentationCtrlWidget(this, d->sharedData);
0201     d->slideCtrlWidget->hide();
0202 
0203     if (!d->sharedData->loop)
0204     {
0205         d->slideCtrlWidget->setEnabledPrev(false);
0206     }
0207 
0208     connect(d->slideCtrlWidget, SIGNAL(signalPause()),
0209             this, SLOT(slotPause()));
0210 
0211     connect(d->slideCtrlWidget, SIGNAL(signalPlay()),
0212             this, SLOT(slotPlay()));
0213 
0214     connect(d->slideCtrlWidget, SIGNAL(signalNext()),
0215             this, SLOT(slotNext()));
0216 
0217     connect(d->slideCtrlWidget, SIGNAL(signalPrev()),
0218             this, SLOT(slotPrev()));
0219 
0220     connect(d->slideCtrlWidget, SIGNAL(signalClose()),
0221             this, SLOT(slotClose()));
0222 
0223 #ifdef HAVE_MEDIAPLAYER
0224 
0225     d->playbackWidget = new PresentationAudioWidget(this, d->sharedData->soundtrackUrls, d->sharedData);
0226     d->playbackWidget->hide();
0227     d->playbackWidget->move(d->deskX, d->deskY);
0228 
0229 #endif
0230 
0231     int w = d->slideCtrlWidget->width() - 1;
0232     d->slideCtrlWidget->move(d->deskX + d->deskWidth - w, d->deskY);
0233 
0234     // -- Minimal texture size (opengl specs) --------------
0235 
0236     d->width        = 64;
0237     d->height       = 64;
0238 
0239     // -- Margin -------------------------------------------
0240 
0241     d->xMargin      = int (d->deskWidth / d->width);
0242     d->yMargin      = int (d->deskWidth / d->height);
0243 
0244     // ------------------------------------------------------------------
0245 
0246     d->fileIndex    = -1; // start with -1
0247     d->timeout      = d->sharedData->delay;
0248     d->imageLoader  = new PresentationLoader(d->sharedData, width(), height(), d->fileIndex);
0249 
0250     // --------------------------------------------------
0251 
0252     registerEffects();
0253 
0254     if (d->sharedData->effectNameGL == QLatin1String("Random"))
0255     {
0256         d->effect = getRandomEffect();
0257         d->random = true;
0258     }
0259     else
0260     {
0261         d->effect = d->effects[d->sharedData->effectNameGL];
0262 
0263         if (!d->effect)
0264         {
0265             d->effect = d->effects[QLatin1String("None")];
0266         }
0267 
0268         d->random = false;
0269     }
0270 
0271     // --------------------------------------------------
0272 
0273     d->timer = new QTimer(this);
0274 
0275     connect(d->timer, SIGNAL(timeout()),
0276             this, SLOT(slotTimeOut()));
0277 
0278     d->timer->setSingleShot(true);
0279     d->timer->start(500);
0280 
0281     // -- hide cursor when not moved --------------------
0282 
0283     d->mouseMoveTimer = new QTimer(this);
0284     d->mouseMoveTimer->setSingleShot(true);
0285 
0286     connect(d->mouseMoveTimer, SIGNAL(timeout()),
0287             this, SLOT(slotMouseMoveTimeOut()));
0288 
0289     setMouseTracking(true);
0290     slotMouseMoveTimeOut();
0291 
0292 #ifdef HAVE_MEDIAPLAYER
0293 
0294     if (d->sharedData->soundtrackPlay)
0295     {
0296         d->playbackWidget->slotPlay();
0297     }
0298 
0299 #endif
0300 
0301 }
0302 
0303 PresentationGL::~PresentationGL()
0304 {
0305 
0306 #ifdef HAVE_MEDIAPLAYER
0307 
0308     d->playbackWidget->slotStop();
0309 
0310 #endif
0311 
0312     d->timer->stop();
0313     d->mouseMoveTimer->stop();
0314 
0315     d->texture[0]->destroy();
0316     d->texture[1]->destroy();
0317     d->texture[2]->destroy();
0318 
0319     delete d->texture[0];
0320     delete d->texture[1];
0321     delete d->texture[2];
0322     delete d->imageLoader;
0323     delete d;
0324 }
0325 
0326 void PresentationGL::initializeGL()
0327 {
0328     // Enable Texture Mapping
0329 
0330     glEnable(GL_TEXTURE_2D);
0331 
0332     // Clear The Background Color
0333 
0334     glClearColor(0.0, 0.0, 0.0, 1.0f);
0335 
0336     // Turn Blending On
0337 
0338     glEnable(GL_BLEND);
0339 
0340     // Blending Function For Translucency Based On Source Alpha Value
0341 
0342     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
0343 
0344     // Enable perspective vision
0345 
0346     glClearDepth(1.0f);
0347 
0348     // get the maximum texture value.
0349 
0350     GLint maxTexVal;
0351     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexVal);
0352 
0353     // allow only maximum texture value of 1024. anything bigger and things slow down
0354 
0355     maxTexVal     = qMin(1024, maxTexVal);
0356 
0357     d->width      = d->deskWidth;
0358     d->height     = d->deskHeight;
0359 
0360     d->width      = 1 << (int)ceil(log((float)d->width)  / log((float)2)) ;
0361     d->height     = 1 << (int)ceil(log((float)d->height) / log((float)2));
0362 
0363     d->width      = qMin(maxTexVal, d->width);
0364     d->height     = qMin(maxTexVal, d->height);
0365 
0366     d->texture[0] = new QOpenGLTexture(QOpenGLTexture::Target2D);
0367     d->texture[1] = new QOpenGLTexture(QOpenGLTexture::Target2D);
0368     d->texture[2] = new QOpenGLTexture(QOpenGLTexture::Target2D); // end screen texture
0369 
0370     QImage black(width(), height(), QImage::Format_RGB32);
0371     black.fill(QColor(0, 0, 0).rgb());
0372 
0373     d->texture[0]->setData(black);
0374     d->texture[0]->bind();
0375 }
0376 
0377 void PresentationGL::paintGL()
0378 {
0379     glDisable(GL_DEPTH_TEST);
0380 
0381     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
0382     glLoadIdentity();
0383 
0384     glMatrixMode(GL_PROJECTION);
0385     glLoadIdentity();
0386 
0387     glMatrixMode(GL_MODELVIEW);
0388     glLoadIdentity();
0389 
0390     if (d->endOfShow)
0391     {
0392         showEndOfShow();
0393     }
0394     else
0395     {
0396         if (d->effectRunning && d->effect)
0397         {
0398             (this->*d->effect)();
0399         }
0400         else
0401         {
0402             paintTexture();
0403         }
0404     }
0405 }
0406 
0407 void PresentationGL::resizeGL(int w, int h)
0408 {
0409     // Reset The Current Viewport And Perspective Transformation
0410 
0411     glViewport(0, 0, (GLint)w, (GLint)h);
0412 
0413     glMatrixMode(GL_PROJECTION);
0414     glLoadIdentity();
0415 }
0416 
0417 void PresentationGL::keyPressEvent(QKeyEvent* event)
0418 {
0419     if (!event)
0420     {
0421         return;
0422     }
0423 
0424     d->slideCtrlWidget->keyPressEvent(event);
0425 
0426 #ifdef HAVE_MEDIAPLAYER
0427 
0428     d->playbackWidget->keyPressEvent(event);
0429 
0430 #endif
0431 
0432 }
0433 
0434 void PresentationGL::mousePressEvent(QMouseEvent* e)
0435 {
0436     if (d->endOfShow)
0437     {
0438         slotClose();
0439     }
0440 
0441     if      (e->button() == Qt::LeftButton)
0442     {
0443         d->timer->stop();
0444         d->slideCtrlWidget->setPaused(!d->sharedData->offAutoDelay);
0445         slotNext();
0446     }
0447     else if ((e->button() == Qt::RightButton) && ((d->fileIndex - 1) >= 0))
0448     {
0449         d->timer->stop();
0450         d->slideCtrlWidget->setPaused(!d->sharedData->offAutoDelay);
0451         slotPrev();
0452     }
0453 }
0454 
0455 void PresentationGL::mouseMoveEvent(QMouseEvent* e)
0456 {
0457     setCursor(QCursor(Qt::ArrowCursor));
0458     d->mouseMoveTimer->start(1000);
0459 
0460     if (!d->slideCtrlWidget->canHide()
0461 
0462 #ifdef HAVE_MEDIAPLAYER
0463 
0464         || !d->playbackWidget->canHide()
0465 
0466 #endif
0467 
0468        )
0469     {
0470         return;
0471     }
0472 
0473     QPoint pos(e->pos());
0474 
0475     if ((pos.y() > 20)                     &&
0476         (pos.y() < (d->deskHeight - 20 - 1)))
0477     {
0478         if (d->slideCtrlWidget->isHidden()
0479 
0480 #ifdef HAVE_MEDIAPLAYER
0481 
0482             || d->playbackWidget->isHidden()
0483 
0484 #endif
0485 
0486            )
0487         {
0488             return;
0489         }
0490         else
0491         {
0492             hideOverlays();
0493             setFocus();
0494         }
0495 
0496         return;
0497     }
0498 
0499     showOverlays();
0500 }
0501 
0502 void PresentationGL::wheelEvent(QWheelEvent* e)
0503 {
0504     if (!d->sharedData->enableMouseWheel)
0505     {
0506         return;
0507     }
0508 
0509     if (d->endOfShow)
0510     {
0511         slotClose();
0512     }
0513 
0514     int delta = e->angleDelta().y();
0515 
0516     if      (delta < 0)
0517     {
0518         d->timer->stop();
0519         d->slideCtrlWidget->setPaused(true);
0520         slotNext();
0521     }
0522     else if ((delta > 0) && ((d->fileIndex - 1) >= 0))
0523     {
0524         d->timer->stop();
0525         d->slideCtrlWidget->setPaused(true);
0526         slotPrev();
0527     }
0528 }
0529 
0530 void PresentationGL::registerEffects()
0531 {
0532     d->effects.insert(QLatin1String("None"),    &PresentationGL::effectNone);
0533     d->effects.insert(QLatin1String("Blend"),   &PresentationGL::effectBlend);
0534     d->effects.insert(QLatin1String("Fade"),    &PresentationGL::effectFade);
0535     d->effects.insert(QLatin1String("Rotate"),  &PresentationGL::effectRotate);
0536     d->effects.insert(QLatin1String("Bend"),    &PresentationGL::effectBend);
0537     d->effects.insert(QLatin1String("In Out"),  &PresentationGL::effectInOut);
0538     d->effects.insert(QLatin1String("Slide"),   &PresentationGL::effectSlide);
0539     d->effects.insert(QLatin1String("Flutter"), &PresentationGL::effectFlutter);
0540     d->effects.insert(QLatin1String("Cube"),    &PresentationGL::effectCube);
0541 }
0542 
0543 QStringList PresentationGL::effectNames()
0544 {
0545     QStringList effects;
0546 
0547     effects.append(QLatin1String("None"));
0548     effects.append(QLatin1String("Bend"));
0549     effects.append(QLatin1String("Blend"));
0550     effects.append(QLatin1String("Cube"));
0551     effects.append(QLatin1String("Fade"));
0552     effects.append(QLatin1String("Flutter"));
0553     effects.append(QLatin1String("In Out"));
0554     effects.append(QLatin1String("Rotate"));
0555     effects.append(QLatin1String("Slide"));
0556     effects.append(QLatin1String("Random"));
0557 
0558     return effects;
0559 }
0560 
0561 QMap<QString, QString> PresentationGL::effectNamesI18N()
0562 {
0563     QMap<QString, QString> effects;
0564 
0565     effects[QLatin1String("None")]    = i18nc("Filter Effect: No effect",     "None");
0566     effects[QLatin1String("Bend")]    = i18nc("Filter Effect: Bend",          "Bend");
0567     effects[QLatin1String("Blend")]   = i18nc("Filter Effect: Blend",         "Blend");
0568     effects[QLatin1String("Cube")]    = i18nc("Filter Effect: Cube",          "Cube");
0569     effects[QLatin1String("Fade")]    = i18nc("Filter Effect: Fade",          "Fade");
0570     effects[QLatin1String("Flutter")] = i18nc("Filter Effect: Flutter",       "Flutter");
0571     effects[QLatin1String("In Out")]  = i18nc("Filter Effect: In Out",        "In Out");
0572     effects[QLatin1String("Rotate")]  = i18nc("Filter Effect: Rotate",        "Rotate");
0573     effects[QLatin1String("Slide")]   = i18nc("Filter Effect: Slide",         "Slide");
0574     effects[QLatin1String("Random")]  = i18nc("Filter Effect: Random effect", "Random");
0575 
0576     return effects;
0577 }
0578 
0579 PresentationGL::EffectMethod PresentationGL::getRandomEffect()
0580 {
0581     QMap<QString, EffectMethod>  tmpMap(d->effects);
0582 
0583     tmpMap.remove(QLatin1String("None"));
0584     QStringList t = tmpMap.keys();
0585     int count     = t.count();
0586     int i         = d->randomGenerator->bounded(count);
0587     QString key   = t[i];
0588 
0589     return tmpMap[key];
0590 }
0591 
0592 void PresentationGL::advanceFrame()
0593 {
0594     d->fileIndex++;
0595     d->imageLoader->next();
0596     int num = d->sharedData->urlList.count();
0597 
0598     if (d->fileIndex >= num)
0599     {
0600         if (d->sharedData->loop)
0601         {
0602             d->fileIndex = 0;
0603         }
0604         else
0605         {
0606             d->fileIndex = num - 1;
0607             d->endOfShow = true;
0608             d->slideCtrlWidget->setEnabledPlay(false);
0609             d->slideCtrlWidget->setEnabledNext(false);
0610             d->slideCtrlWidget->setEnabledPrev(false);
0611         }
0612     }
0613 
0614     if (!d->sharedData->loop && !d->endOfShow)
0615     {
0616         d->slideCtrlWidget->setEnabledPrev(d->fileIndex > 0);
0617         d->slideCtrlWidget->setEnabledNext(d->fileIndex < (num - 1));
0618     }
0619 
0620     d->tex1First = !d->tex1First;
0621     d->curr      = (d->curr == 0) ? 1 : 0;
0622 }
0623 
0624 void PresentationGL::previousFrame()
0625 {
0626     d->fileIndex--;
0627     d->imageLoader->prev();
0628     int num = d->sharedData->urlList.count();
0629 
0630     if (d->fileIndex < 0)
0631     {
0632         if (d->sharedData->loop)
0633         {
0634             d->fileIndex = num - 1;
0635         }
0636         else
0637         {
0638             d->fileIndex = 0;
0639             d->endOfShow = true;
0640             d->slideCtrlWidget->setEnabledPlay(false);
0641             d->slideCtrlWidget->setEnabledNext(false);
0642             d->slideCtrlWidget->setEnabledPrev(false);
0643         }
0644     }
0645 
0646     if (!d->sharedData->loop && !d->endOfShow)
0647     {
0648         d->slideCtrlWidget->setEnabledPrev(d->fileIndex > 0);
0649         d->slideCtrlWidget->setEnabledNext(d->fileIndex < (num - 1));
0650     }
0651 
0652     d->tex1First = !d->tex1First;
0653     d->curr      = (d->curr == 0) ? 1 : 0;
0654 }
0655 
0656 void PresentationGL::loadImage()
0657 {
0658     QImage image = d->imageLoader->getCurrent();
0659     int a        = d->tex1First ? 0 : 1;
0660 
0661     if (!image.isNull())
0662     {
0663         QImage black(width(), height(), QImage::Format_RGB32);
0664 
0665         black.fill(QColor(0, 0, 0).rgb());
0666 
0667         montage(image, black);
0668 
0669         if (!d->sharedData->openGlFullScale)
0670         {
0671             black = black.scaled(d->width, d->height,
0672                                  Qt::IgnoreAspectRatio,
0673                                  Qt::SmoothTransformation);
0674         }
0675 
0676         if (d->sharedData->printFileName)
0677         {
0678             printFilename(black);
0679         }
0680 
0681         if (d->sharedData->printProgress)
0682         {
0683             printProgress(black);
0684         }
0685 
0686         if (d->sharedData->printFileComments)
0687         {
0688             printComments(black);
0689         }
0690 
0691         /* create the texture */
0692 
0693         d->texture[a]->destroy();
0694         d->texture[a]->setData(black.mirrored());
0695         d->texture[a]->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
0696         d->texture[a]->setMagnificationFilter(QOpenGLTexture::Linear);
0697         d->texture[a]->bind();
0698     }
0699 }
0700 
0701 void PresentationGL::montage(QImage& top, QImage& bot)
0702 {
0703     int tw = top.width();
0704     int th = top.height();
0705     int bw = bot.width();
0706     int bh = bot.height();
0707 
0708     if ((tw > bw) || (th > bh))
0709     {
0710         qFatal("Top Image should be smaller or same size as Bottom Image");
0711     }
0712 
0713     if (top.depth() != 32)
0714     {
0715         top = top.convertToFormat(QImage::Format_RGB32);
0716     }
0717 
0718     if (bot.depth() != 32)
0719     {
0720         bot = bot.convertToFormat(QImage::Format_RGB32);
0721     }
0722 
0723     int sw = bw / 2 - tw / 2; // int ew = bw/2 + tw/2;
0724     int sh = bh / 2 - th / 2;
0725     int eh = bh / 2 + th / 2;
0726 
0727     unsigned int* tdata = reinterpret_cast<unsigned int*>(top.scanLine(0));
0728     unsigned int* bdata = nullptr;
0729 
0730     for (int y = sh ; y < eh ; ++y)
0731     {
0732         bdata = reinterpret_cast<unsigned int*>(bot.scanLine(y)) + sw;
0733 
0734         for (int x = 0 ; x < tw ; ++x)
0735         {
0736             *(bdata++) = *(tdata++);
0737         }
0738     }
0739 }
0740 
0741 void PresentationGL::printFilename(QImage& layer)
0742 {
0743     QFileInfo fileinfo(d->sharedData->urlList[d->fileIndex].toLocalFile());
0744     QString filename = fileinfo.fileName();
0745     QPixmap pix      = generateOutlinedTextPixmap(filename);
0746 
0747     // --------------------------------------------------------
0748 
0749     QPainter painter;
0750     painter.begin(&layer);
0751     painter.drawPixmap(d->xMargin, layer.height() - d->yMargin - pix.height(), pix);
0752     painter.end();
0753 }
0754 
0755 void PresentationGL::printProgress(QImage& layer)
0756 {
0757     QString progress(QString::number(d->fileIndex + 1) + QLatin1Char('/') +
0758                                      QString::number(d->sharedData->urlList.count()));
0759 
0760     QPixmap pix = generateOutlinedTextPixmap(progress);
0761 
0762     QPainter painter;
0763     painter.begin(&layer);
0764     painter.drawPixmap(layer.width() - d->xMargin - pix.width(), d->yMargin, pix);
0765     painter.end();
0766 }
0767 
0768 void PresentationGL::printComments(QImage& layer)
0769 {
0770     DItemInfo info(d->sharedData->iface->itemInfo(d->imageLoader->currPath()));
0771     QString comments = info.comment();
0772 
0773     int yPos = 5; // Text Y coordinate
0774 
0775     if (d->sharedData->printFileName)
0776     {
0777         yPos += 20;
0778     }
0779 
0780     QStringList commentsByLines;
0781 
0782     uint commentsIndex = 0; // Comments QString index
0783 
0784     while (commentsIndex < (uint) comments.length())
0785     {
0786         QString newLine;
0787         bool breakLine = false; // End Of Line found
0788         uint currIndex; //  Comments QString current index
0789 
0790         // Check minimal lines dimension
0791 
0792         int commentsLinesLengthLocal = d->sharedData->commentsLinesLength;
0793 
0794         for (currIndex = commentsIndex ; (currIndex < (uint)comments.length()) && !breakLine ; ++currIndex)
0795         {
0796             if (comments[currIndex] == QLatin1Char('\n') || comments[currIndex].isSpace())
0797             {
0798                 breakLine = true;
0799             }
0800         }
0801 
0802         if (commentsLinesLengthLocal <= (int)((currIndex - commentsIndex)))
0803         {
0804             commentsLinesLengthLocal = (currIndex - commentsIndex);
0805         }
0806 
0807         breakLine = false;
0808 
0809         for (currIndex = commentsIndex ; (currIndex <= (commentsIndex + commentsLinesLengthLocal)) &&
0810              (currIndex < (uint)comments.length()) && !breakLine ; ++currIndex )
0811         {
0812             breakLine = (comments[currIndex] == QLatin1Char('\n')) ? true : false;
0813 
0814             if (breakLine)
0815             {
0816                 newLine.append(QLatin1Char(' '));
0817             }
0818             else
0819             {
0820                 newLine.append(comments[currIndex]);
0821             }
0822         }
0823 
0824         commentsIndex = currIndex; // The line is ended
0825 
0826         if (commentsIndex != (uint) comments.length())
0827         {
0828             while (!newLine.endsWith(QLatin1Char(' ')))
0829             {
0830                 newLine.truncate(newLine.length() - 1);
0831                 commentsIndex--;
0832             }
0833         }
0834 
0835         commentsByLines.prepend(newLine.trimmed());
0836     }
0837 
0838     yPos += int(2.0 * d->sharedData->captionFont->pointSize());
0839 
0840     QFont  font(*d->sharedData->captionFont);
0841     QColor fgColor(d->sharedData->commentsFontColor);
0842     QColor bgColor(d->sharedData->commentsBgColor);
0843     bool   drawTextOutline = d->sharedData->commentsDrawOutline;
0844     int    opacity = d->sharedData->bgOpacity;
0845 
0846     for (int lineNumber = 0 ; lineNumber < (int)commentsByLines.count() ; ++lineNumber)
0847     {
0848         QPixmap pix = generateCustomOutlinedTextPixmap(commentsByLines[lineNumber],
0849                                                        font, fgColor, bgColor, opacity, drawTextOutline);
0850 
0851         QPainter painter;
0852         painter.begin(&layer);
0853 
0854         int xPos = (layer.width() / 2) - (pix.width() / 2);
0855         painter.drawPixmap(xPos, layer.height() - pix.height() - yPos, pix);
0856 
0857         painter.end();
0858 
0859         yPos += int(pix.height() + d->height / 400);
0860     }
0861 }
0862 
0863 void PresentationGL::showEndOfShow()
0864 {
0865     QPixmap pix(width(), height());
0866     pix.fill(Qt::black);
0867 
0868     QFont fn(font());
0869     fn.setPointSize(fn.pointSize() + 10);
0870     fn.setBold(true);
0871 
0872     QPainter p(&pix);
0873     p.setPen(Qt::white);
0874     p.setFont(fn);
0875     p.drawText(20, 50, i18n("Slideshow Completed"));
0876     p.drawText(20, 100, i18n("Click to Exit..."));
0877 
0878 //     QPixmap logoPixmap = KPSvgPixmapRenderer(width() / 6, width() / 6).getPixmap();
0879 //     p.drawPixmap(width()-(width()/12)-logoPixmap.width(),
0880 //                  height()-(height()/12)-logoPixmap.height(),
0881 //                  logoPixmap);
0882 
0883     p.end();
0884 
0885     QImage image(pix.toImage());
0886 
0887     /* create the texture */
0888 
0889     d->texture[2]->destroy();
0890     d->texture[2]->setData(image.mirrored());
0891     d->texture[2]->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
0892     d->texture[2]->setMagnificationFilter(QOpenGLTexture::Linear);
0893     d->texture[2]->bind();
0894 
0895     /* paint the texture */
0896 
0897     glMatrixMode(GL_MODELVIEW);
0898     glLoadIdentity();
0899 
0900     glBegin(GL_QUADS);
0901     {
0902         glColor4f(1.0, 1.0, 1.0, 1.0);
0903         glTexCoord2f(0, 0);
0904         glVertex3f(-1.0, -1.0, 0);
0905 
0906         glTexCoord2f(1, 0);
0907         glVertex3f(1.0, -1.0, 0);
0908 
0909         glTexCoord2f(1, 1);
0910         glVertex3f(1.0, 1.0, 0);
0911 
0912         glTexCoord2f(0, 1);
0913         glVertex3f(-1.0, 1.0, 0);
0914     }
0915 
0916     glEnd();
0917 }
0918 
0919 void PresentationGL::showOverlays()
0920 {
0921     if (d->slideCtrlWidget->isHidden())
0922     {
0923         int w = d->slideCtrlWidget->width() - 1;
0924         d->slideCtrlWidget->move(d->deskWidth - w, 0);
0925         d->slideCtrlWidget->show();
0926     }
0927 
0928 #ifdef HAVE_MEDIAPLAYER
0929 
0930     if (d->playbackWidget->isHidden())
0931     {
0932         d->playbackWidget->move(0, 0);
0933         d->playbackWidget->show();
0934     }
0935 
0936 #endif
0937 
0938 }
0939 
0940 void PresentationGL::hideOverlays()
0941 {
0942     d->slideCtrlWidget->hide();
0943 
0944 #ifdef HAVE_MEDIAPLAYER
0945 
0946     d->playbackWidget->hide();
0947 
0948 #endif
0949 
0950 }
0951 
0952 void PresentationGL::slotTimeOut()
0953 {
0954     if (!d->effect)
0955     {
0956         qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "PresentationGL: No transition method";
0957         d->effect = &PresentationGL::effectNone;
0958     }
0959 
0960     if (d->effectRunning)
0961     {
0962         d->timeout = 10;
0963     }
0964     else
0965     {
0966         if (d->timeout == 0)
0967         {
0968             // effect was running and is complete now
0969             // run timer while showing current image
0970 
0971             d->timeout = d->sharedData->delay;
0972             d->i       = 0;
0973         }
0974         else
0975         {
0976 
0977             // timed out after showing current image
0978             // load next image and start effect
0979 
0980             if (d->random)
0981             {
0982                 d->effect = getRandomEffect();
0983             }
0984 
0985             if (d->sharedData->offAutoDelay)
0986             {
0987                 d->effect = &PresentationGL::effectNone;
0988                 d->timer->stop();
0989             }
0990 
0991             advanceFrame();
0992 
0993             if (d->endOfShow)
0994             {
0995                 update();
0996                 return;
0997             }
0998 
0999             loadImage();
1000 
1001             d->timeout       = 10;
1002             d->effectRunning = true;
1003             d->i             = 0;
1004 
1005         }
1006     }
1007 
1008     update();
1009 
1010     d->timer->start(d->timeout);
1011 
1012     if (d->sharedData->offAutoDelay)
1013     {
1014         d->timer->stop();
1015     }
1016 }
1017 
1018 void PresentationGL::slotMouseMoveTimeOut()
1019 {
1020     QPoint pos(QCursor::pos());
1021 
1022     if ((pos.y() < 20)                       ||
1023         (pos.y() > (d->deskHeight - 20 - 1)) ||
1024         !d->timer->isActive()                ||
1025         d->slideCtrlWidget->underMouse()
1026 
1027 #ifdef HAVE_MEDIAPLAYER
1028 
1029         || d->playbackWidget->underMouse()
1030 
1031 #endif
1032 
1033        )
1034     {
1035         return;
1036     }
1037 
1038     setCursor(QCursor(Qt::BlankCursor));
1039 }
1040 
1041 void PresentationGL::paintTexture()
1042 {
1043     glMatrixMode(GL_MODELVIEW);
1044     glLoadIdentity();
1045     GLuint tex = d->texture[d->curr]->textureId();
1046     glBindTexture(GL_TEXTURE_2D, tex);
1047 
1048     glBegin(GL_QUADS);
1049     {
1050         glColor4f(1.0, 1.0, 1.0, 1.0);
1051         glTexCoord2f(0, 0);
1052         glVertex3f(-1.0, -1.0, 0);
1053 
1054         glTexCoord2f(1, 0);
1055         glVertex3f(1.0, -1.0, 0);
1056 
1057         glTexCoord2f(1, 1);
1058         glVertex3f(1.0, 1.0, 0);
1059 
1060         glTexCoord2f(0, 1);
1061         glVertex3f(-1.0, 1.0, 0);
1062     }
1063 
1064     glEnd();
1065 }
1066 
1067 void PresentationGL::effectNone()
1068 {
1069     paintTexture();
1070     d->effectRunning = false;
1071     d->timeout       = 0;
1072 }
1073 
1074 void PresentationGL::effectBlend()
1075 {
1076     if (d->i > 100)
1077     {
1078         paintTexture();
1079         d->effectRunning = false;
1080         d->timeout       = 0;
1081         return;
1082     }
1083 
1084     int a     = (d->curr == 0) ? 1 : 0;
1085     int b     =  d->curr;
1086 
1087     GLuint ta = d->texture[a]->textureId();
1088     GLuint tb = d->texture[b]->textureId();
1089 
1090     glBindTexture(GL_TEXTURE_2D, ta);
1091 
1092     glBegin(GL_QUADS);
1093     {
1094         glColor4f(1.0, 1.0, 1.0, 1.0);
1095         glTexCoord2f(0, 0);
1096         glVertex3f(-1.0f, -1.0f, 0);
1097 
1098         glTexCoord2f(1, 0);
1099         glVertex3f(1.0f, -1.0f, 0);
1100 
1101         glTexCoord2f(1, 1);
1102         glVertex3f(1.0f, 1.0f, 0);
1103 
1104         glTexCoord2f(0, 1);
1105         glVertex3f(-1.0f, 1.0f, 0);
1106     }
1107 
1108     glEnd();
1109     glBindTexture(GL_TEXTURE_2D, tb);
1110 
1111     glBegin(GL_QUADS);
1112     {
1113         glColor4f(1.0, 1.0, 1.0, 1.0 / (100.0)*(float)d->i);
1114         glTexCoord2f(0, 0);
1115         glVertex3f(-1.0f, -1.0f, 0);
1116 
1117         glTexCoord2f(1, 0);
1118         glVertex3f(1.0f, -1.0f, 0);
1119 
1120         glTexCoord2f(1, 1);
1121         glVertex3f(1.0f, 1.0f, 0);
1122 
1123         glTexCoord2f(0, 1);
1124         glVertex3f(-1.0f, 1.0f, 0);
1125     }
1126 
1127     glEnd();
1128 
1129     d->i++;
1130 }
1131 
1132 void PresentationGL::effectFade()
1133 {
1134     if (d->i > 100)
1135     {
1136         paintTexture();
1137         d->effectRunning = false;
1138         d->timeout       = 0;
1139         return;
1140     }
1141 
1142     int a;
1143     float opacity;
1144 
1145     if (d->i <= 50)
1146     {
1147         a =  (d->curr == 0) ? 1 : 0;
1148         opacity = 1.0 - 1.0 / 50.0 * (float)(d->i);
1149     }
1150     else
1151     {
1152         opacity = 1.0 / 50.0 * (float)(d->i - 50.0);
1153         a = d->curr;
1154     }
1155 
1156     GLuint ta = d->texture[a]->textureId();
1157     glBindTexture(GL_TEXTURE_2D, ta);
1158 
1159     glBegin(GL_QUADS);
1160     {
1161         glColor4f(1.0, 1.0, 1.0, opacity);
1162         glTexCoord2f(0, 0);
1163         glVertex3f(-1.0f, -1.0f, 0);
1164 
1165         glTexCoord2f(1, 0);
1166         glVertex3f(1.0f, -1.0f, 0);
1167 
1168         glTexCoord2f(1, 1);
1169         glVertex3f(1.0f, 1.0f, 0);
1170 
1171         glTexCoord2f(0, 1);
1172         glVertex3f(-1.0f, 1.0f, 0);
1173     }
1174 
1175     glEnd();
1176 
1177     d->i++;
1178 }
1179 
1180 void PresentationGL::effectRotate()
1181 {
1182     if (d->i > 100)
1183     {
1184         paintTexture();
1185         d->effectRunning = false;
1186         d->timeout       = 0;
1187         return;
1188     }
1189 
1190     if (d->i == 0)
1191     {
1192         d->dir = d->randomGenerator->bounded(2);
1193     }
1194 
1195     int a     = (d->curr == 0) ? 1 : 0;
1196     int b     = d->curr;
1197 
1198     GLuint ta = d->texture[a]->textureId();
1199     GLuint tb = d->texture[b]->textureId();
1200     glBindTexture(GL_TEXTURE_2D, tb);
1201 
1202     glBegin(GL_QUADS);
1203     {
1204         glColor4f(1.0, 1.0, 1.0, 1.0);
1205         glTexCoord2f(0, 0);
1206         glVertex3f(-1.0f, -1.0f, 0);
1207 
1208         glTexCoord2f(1, 0);
1209         glVertex3f(1.0f, -1.0f, 0);
1210 
1211         glTexCoord2f(1, 1);
1212         glVertex3f(1.0f, 1.0f, 0);
1213 
1214         glTexCoord2f(0, 1);
1215         glVertex3f(-1.0f, 1.0f, 0);
1216     }
1217 
1218     glEnd();
1219 
1220     glMatrixMode(GL_MODELVIEW);
1221     glLoadIdentity();
1222     float rotate = 360.0 / 100.0 * (float)d->i;
1223     glRotatef( ((d->dir == 0) ? -1 : 1) * rotate, 0.0, 0.0, 1.0);
1224     float scale  = 1.0 / 100.0 * (100.0 - (float)(d->i));
1225     glScalef(scale, scale, 1.0);
1226     glBindTexture(GL_TEXTURE_2D, ta);
1227 
1228     glBegin(GL_QUADS);
1229     {
1230         glColor4f(1.0, 1.0, 1.0, 1.0);
1231         glTexCoord2f(0, 0);
1232         glVertex3f(-1.0f, -1.0f, 0);
1233 
1234         glTexCoord2f(1, 0);
1235         glVertex3f(1.0f, -1.0f, 0);
1236 
1237         glTexCoord2f(1, 1);
1238         glVertex3f(1.0f, 1.0f, 0);
1239 
1240         glTexCoord2f(0, 1);
1241         glVertex3f(-1.0f, 1.0f, 0);
1242     }
1243 
1244     glEnd();
1245 
1246     d->i++;
1247 }
1248 
1249 void PresentationGL::effectBend()
1250 {
1251     if (d->i > 100)
1252     {
1253         paintTexture();
1254         d->effectRunning = false;
1255         d->timeout       = 0;
1256         return;
1257     }
1258 
1259     if (d->i == 0)
1260     {
1261         d->dir = d->randomGenerator->bounded(2);
1262     }
1263 
1264     int a     = (d->curr == 0) ? 1 : 0;
1265     int b     = d->curr;
1266 
1267     GLuint ta = d->texture[a]->textureId();
1268     GLuint tb = d->texture[b]->textureId();
1269     glBindTexture(GL_TEXTURE_2D, tb);
1270 
1271     glBegin(GL_QUADS);
1272 
1273     {
1274         glColor4f(1.0, 1.0, 1.0, 1.0);
1275         glTexCoord2f(0, 0);
1276         glVertex3f(-1.0f, -1.0f, 0);
1277 
1278         glTexCoord2f(1, 0);
1279         glVertex3f(1.0f, -1.0f, 0);
1280 
1281         glTexCoord2f(1, 1);
1282         glVertex3f(1.0f, 1.0f, 0);
1283 
1284         glTexCoord2f(0, 1);
1285         glVertex3f(-1.0f, 1.0f, 0);
1286     }
1287 
1288     glEnd();
1289 
1290     glMatrixMode(GL_MODELVIEW);
1291     glLoadIdentity();
1292     glRotatef(90.0 / 100.0*(float)d->i,
1293               (d->dir == 0) ? 1.0 : 0.0,
1294               (d->dir == 1) ? 1.0 : 0.0,
1295               0.0);
1296 
1297     glBindTexture(GL_TEXTURE_2D, ta);
1298 
1299     glBegin(GL_QUADS);
1300     {
1301         glColor4f(1.0, 1.0, 1.0, 1.0);
1302         glTexCoord2f(0, 0);
1303         glVertex3f(-1.0f, -1.0f, 0);
1304 
1305         glTexCoord2f(1, 0);
1306         glVertex3f(1.0f, -1.0f, 0);
1307 
1308         glTexCoord2f(1, 1);
1309         glVertex3f(1.0f, 1.0f, 0);
1310 
1311         glTexCoord2f(0, 1);
1312         glVertex3f(-1.0f, 1.0f, 0);
1313     }
1314 
1315     glEnd();
1316 
1317     d->i++;
1318 }
1319 
1320 void PresentationGL::effectInOut()
1321 {
1322     if (d->i > 100)
1323     {
1324         paintTexture();
1325         d->effectRunning = false;
1326         d->timeout       = 0;
1327         return;
1328     }
1329 
1330     if (d->i == 0)
1331     {
1332         d->dir = d->randomGenerator->bounded(1, 5);
1333     }
1334 
1335     int a;
1336     bool out;
1337 
1338     if (d->i <= 50)
1339     {
1340         a   = (d->curr == 0) ? 1 : 0;
1341         out = 1;
1342     }
1343     else
1344     {
1345         a   = d->curr;
1346         out = 0;
1347     }
1348 
1349     GLuint ta  = d->texture[a]->textureId();
1350     glMatrixMode(GL_MODELVIEW);
1351     glLoadIdentity();
1352     float t    = out ? 1.0 / 50.0 * (50.0 - d->i) : 1.0 / 50.0 * (d->i - 50.0);
1353     glScalef(t, t, 1.0);
1354     t          = 1.0 - t;
1355     glTranslatef((d->dir % 2 == 0) ? ((d->dir == 2) ? 1 : -1) * t : 0.0,
1356                  (d->dir % 2 == 1) ? ((d->dir == 1) ? 1 : -1) * t : 0.0,
1357                  0.0);
1358 
1359     glBindTexture(GL_TEXTURE_2D, ta);
1360 
1361     glBegin(GL_QUADS);
1362     {
1363         glColor4f(1.0, 1.0, 1.0, 1.0);
1364 
1365         glColor4f(1.0, 1.0, 1.0, 1.0);
1366         glTexCoord2f(0, 0);
1367         glVertex3f(-1.0f, -1.0f, 0);
1368 
1369         glTexCoord2f(1, 0);
1370         glVertex3f(1.0f, -1.0f, 0);
1371 
1372         glTexCoord2f(1, 1);
1373         glVertex3f(1.0f, 1.0f, 0);
1374 
1375         glTexCoord2f(0, 1);
1376         glVertex3f(-1.0f, 1.0f, 0);
1377     }
1378 
1379     glEnd();
1380 
1381     d->i++;
1382 }
1383 
1384 void PresentationGL::effectSlide()
1385 {
1386     if (d->i > 100)
1387     {
1388         paintTexture();
1389         d->effectRunning = false;
1390         d->timeout       = 0;
1391         return;
1392     }
1393 
1394     if (d->i == 0)
1395     {
1396         d->dir = d->randomGenerator->bounded(1, 5);
1397     }
1398 
1399     int a     = (d->curr == 0) ? 1 : 0;
1400     int b     =  d->curr;
1401     GLuint ta = d->texture[a]->textureId();
1402     GLuint tb = d->texture[b]->textureId();
1403     glBindTexture(GL_TEXTURE_2D, tb);
1404 
1405     glBegin(GL_QUADS);
1406     {
1407         glColor4f(1.0, 1.0, 1.0, 1.0);
1408         glTexCoord2f(0, 0);
1409         glVertex3f(-1.0f, -1.0f, 0);
1410 
1411         glTexCoord2f(1, 0);
1412         glVertex3f(1.0f, -1.0f, 0);
1413 
1414         glTexCoord2f(1, 1);
1415         glVertex3f(1.0f, 1.0f, 0);
1416 
1417         glTexCoord2f(0, 1);
1418         glVertex3f(-1.0f, 1.0f, 0);
1419     }
1420 
1421     glEnd();
1422 
1423     glMatrixMode(GL_MODELVIEW);
1424     glLoadIdentity();
1425     float trans = 2.0 / 100.0 * (float)d->i;
1426     glTranslatef((d->dir % 2 == 0) ? ((d->dir == 2) ? 1 : -1) * trans : 0.0,
1427                  (d->dir % 2 == 1) ? ((d->dir == 1) ? 1 : -1) * trans : 0.0,
1428                  0.0);
1429 
1430     glBindTexture(GL_TEXTURE_2D, ta);
1431 
1432     glBegin(GL_QUADS);
1433     {
1434         glColor4f(1.0, 1.0, 1.0, 1.0);
1435 
1436         glColor4f(1.0, 1.0, 1.0, 1.0);
1437         glTexCoord2f(0, 0);
1438         glVertex3f(-1.0f, -1.0f, 0);
1439 
1440         glTexCoord2f(1, 0);
1441         glVertex3f(1.0f, -1.0f, 0);
1442 
1443         glTexCoord2f(1, 1);
1444         glVertex3f(1.0f, 1.0f, 0);
1445 
1446         glTexCoord2f(0, 1);
1447         glVertex3f(-1.0f, 1.0f, 0);
1448     }
1449 
1450     glEnd();
1451 
1452     d->i++;
1453 }
1454 
1455 void PresentationGL::effectFlutter()
1456 {
1457     if (d->i > 100)
1458     {
1459         paintTexture();
1460         d->effectRunning = false;
1461         d->timeout       = 0;
1462         return;
1463     }
1464 
1465     int a     = (d->curr == 0) ? 1 : 0;
1466     int b     =  d->curr;
1467     GLuint ta = d->texture[a]->textureId();
1468     GLuint tb = d->texture[b]->textureId();
1469 
1470     if (d->i == 0)
1471     {
1472         for (int x = 0 ; x < 40 ; ++x)
1473         {
1474             for (int y = 0 ; y < 40 ; ++y)
1475             {
1476                 d->points[x][y][0] = (float) (x / 20.0f - 1.0f);
1477                 d->points[x][y][1] = (float) (y / 20.0f - 1.0f);
1478                 d->points[x][y][2] = (float) sin((x / 20.0f - 1.0f) * 3.141592654 * 2.0f) / 5.0;
1479             }
1480         }
1481     }
1482 
1483     glBindTexture(GL_TEXTURE_2D, tb);
1484 
1485     glBegin(GL_QUADS);
1486     {
1487         glColor4f(1.0, 1.0, 1.0, 1.0);
1488         glTexCoord2f(0, 0);
1489         glVertex3f(-1.0f, -1.0f, 0);
1490 
1491         glTexCoord2f(1, 0);
1492         glVertex3f(1.0f, -1.0f, 0);
1493 
1494         glTexCoord2f(1, 1);
1495         glVertex3f(1.0f, 1.0f, 0);
1496 
1497         glTexCoord2f(0, 1);
1498         glVertex3f(-1.0f, 1.0f, 0);
1499     }
1500 
1501     glEnd();
1502 
1503     glMatrixMode(GL_MODELVIEW);
1504     glLoadIdentity();
1505     float rotate = 60.0 / 100.0 * (float)d->i;
1506     glRotatef(rotate, 1.0f, 0.0f, 0.0f);
1507     float scale  = 1.0 / 100.0 * (100.0 - (float)d->i);
1508     glScalef(scale, scale, scale);
1509     glTranslatef(1.0 / 100.0*(float)d->i, 1.0 / 100.0*(float)d->i, 0.0);
1510     glBindTexture(GL_TEXTURE_2D, ta);
1511 
1512     glBegin(GL_QUADS);
1513     {
1514         glColor4f(1.0, 1.0, 1.0, 1.0);
1515 
1516         float float_x, float_y, float_xb, float_yb;
1517         int x, y;
1518 
1519         for (x = 0 ; x < 39 ; ++x)
1520         {
1521             for (y = 0 ; y < 39 ; ++y)
1522             {
1523                 float_x  = (float) x / 40.0f;
1524                 float_y  = (float) y / 40.0f;
1525                 float_xb = (float) (x + 1) / 40.0f;
1526                 float_yb = (float) (y + 1) / 40.0f;
1527                 glTexCoord2f(float_x, float_y);
1528                 glVertex3f(d->points[x][y][0], d->points[x][y][1], d->points[x][y][2]);
1529                 glTexCoord2f(float_x, float_yb);
1530                 glVertex3f(d->points[x][y + 1][0], d->points[x][y + 1][1], d->points[x][y + 1][2]);
1531                 glTexCoord2f(float_xb, float_yb);
1532                 glVertex3f(d->points[x + 1][y + 1][0], d->points[x + 1][y + 1][1], d->points[x + 1][y + 1][2]);
1533                 glTexCoord2f(float_xb, float_y);
1534                 glVertex3f(d->points[x + 1][y][0], d->points[x + 1][y][1], d->points[x + 1][y][2]);
1535             }
1536         }
1537     }
1538 
1539     glEnd();
1540 
1541     // wave every two iterations
1542 
1543     if ((d->i % 2) == 0)
1544     {
1545 
1546         float hold;
1547         int x, y;
1548 
1549         for (y = 0 ; y < 40 ; ++y)
1550         {
1551             hold = d->points[0][y][2];
1552 
1553             for (x = 0 ; x < 39 ; ++x)
1554             {
1555                 d->points[x][y][2] = d->points[x + 1][y][2];
1556             }
1557 
1558             d->points[39][y][2] = hold;
1559         }
1560     }
1561 
1562     d->i++;
1563 }
1564 
1565 void PresentationGL::effectCube()
1566 {
1567     int tot      = 200;
1568     int rotStart = 50;
1569 
1570     if (d->i > tot)
1571     {
1572         paintTexture();
1573         d->effectRunning = false;
1574         d->timeout       = 0;
1575         return;
1576     }
1577 
1578     // Enable perspective vision
1579 
1580     glEnable(GL_DEPTH_TEST);
1581     glDepthFunc(GL_LEQUAL);
1582     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1583 
1584     int a     = (d->curr == 0) ? 1 : 0;
1585     int b     =  d->curr;
1586     GLuint ta = d->texture[a]->textureId();
1587     GLuint tb = d->texture[b]->textureId();
1588     glMatrixMode(GL_PROJECTION);
1589     glLoadIdentity();
1590 
1591 //    float PI    = 4.0 * atan(1.0);
1592     float znear = 3.0;
1593 //    float theta = 2.0 * atan2((float)2.0 / (float)2.0, (float)znear);
1594 //    theta       = theta * 180.0 / PI;
1595 
1596     glFrustum(-1.0, 1.0, -1.0, 1.0, znear - 0.01, 10.0);
1597 
1598     static float xrot;
1599     static float yrot;
1600 //    static float zrot;
1601 
1602     if (d->i == 0)
1603     {
1604         xrot = 0.0;
1605         yrot = 0.0;
1606 //        zrot = 0.0;
1607     }
1608 
1609     glMatrixMode( GL_MODELVIEW );
1610     glLoadIdentity();
1611 
1612     float trans = 5.0 * (float)((d->i <= tot / 2) ? d->i : tot - d->i) / (float)tot;
1613     glTranslatef(0.0, 0.0, -znear - 1.0 - trans);
1614 
1615     glRotatef(xrot, 1.0f, 0.0f, 0.0f);
1616     glRotatef(yrot, 0.0f, 1.0f, 0.0f);
1617     glBindTexture(GL_TEXTURE_2D, 0);
1618 
1619     glBegin(GL_QUADS);
1620     {
1621         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1622 
1623         /* Front Face */
1624 
1625         glVertex3f( -1.00f, -1.00f,  0.99f );
1626         glVertex3f(  1.00f, -1.00f,  0.99f );
1627         glVertex3f(  1.00f,  1.00f,  0.99f );
1628         glVertex3f( -1.00f,  1.00f,  0.99f );
1629 
1630         /* Back Face */
1631 
1632         glVertex3f( -1.00f, -1.00f, -0.99f );
1633         glVertex3f( -1.00f,  1.00f, -0.99f );
1634         glVertex3f(  1.00f,  1.00f, -0.99f );
1635         glVertex3f(  1.00f, -1.00f, -0.99f );
1636 
1637         /* Top Face */
1638 
1639         glVertex3f( -1.00f,  0.99f, -1.00f );
1640         glVertex3f( -1.00f,  0.99f,  1.00f );
1641         glVertex3f(  1.00f,  0.99f,  1.00f );
1642         glVertex3f(  1.00f,  0.99f, -1.00f );
1643 
1644         /* Bottom Face */
1645 
1646         glVertex3f( -1.00f, -0.99f, -1.00f );
1647         glVertex3f(  1.00f, -0.99f, -1.00f );
1648         glVertex3f(  1.00f, -0.99f,  1.00f );
1649         glVertex3f( -1.00f, -0.99f,  1.00f );
1650 
1651         /* Right face */
1652 
1653         glVertex3f( 0.99f, -1.00f, -1.00f );
1654         glVertex3f( 0.99f,  1.00f, -1.00f );
1655         glVertex3f( 0.99f,  1.00f,  1.00f );
1656         glVertex3f( 0.99f, -1.00f,  1.00f );
1657 
1658         /* Left Face */
1659 
1660         glVertex3f( -0.99f, -1.00f, -1.00f );
1661         glVertex3f( -0.99f, -1.00f,  1.00f );
1662         glVertex3f( -0.99f,  1.00f,  1.00f );
1663         glVertex3f( -0.99f,  1.00f, -1.00f );
1664     }
1665 
1666     glEnd();
1667     glBindTexture(GL_TEXTURE_2D, ta);
1668 
1669     glBegin(GL_QUADS);
1670     {
1671         glColor4d(1.0, 1.0, 1.0, 1.0);
1672 
1673         // Front Face
1674 
1675         glTexCoord2f( 0.0f, 0.0f );
1676         glVertex3f( -1.0f, -1.0f,  1.00f );
1677         glTexCoord2f( 1.0f, 0.0f );
1678         glVertex3f(  1.0f, -1.0f,  1.00f );
1679         glTexCoord2f( 1.0f, 1.0f );
1680         glVertex3f(  1.0f,  1.0f,  1.00f );
1681         glTexCoord2f( 0.0f, 1.0f );
1682         glVertex3f( -1.0f,  1.0f,  1.00f );
1683 
1684         // Top Face
1685 
1686         glTexCoord2f( 1.0f, 1.0f );
1687         glVertex3f( -1.0f,  1.00f, -1.0f );
1688         glTexCoord2f( 1.0f, 0.0f );
1689         glVertex3f( -1.0f,  1.00f,  1.0f );
1690         glTexCoord2f( 0.0f, 0.0f );
1691         glVertex3f(  1.0f,  1.00f,  1.0f );
1692         glTexCoord2f( 0.0f, 1.0f );
1693         glVertex3f(  1.0f,  1.00f, -1.0f );
1694 
1695         // Bottom Face
1696 
1697         glTexCoord2f( 0.0f, 1.0f );
1698         glVertex3f( -1.0f, -1.00f, -1.0f );
1699         glTexCoord2f( 1.0f, 1.0f );
1700         glVertex3f(  1.0f, -1.00f, -1.0f );
1701         glTexCoord2f( 1.0f, 0.0f );
1702         glVertex3f(  1.0f, -1.00f,  1.0f );
1703         glTexCoord2f( 0.0f, 0.0f );
1704         glVertex3f( -1.0f, -1.00f,  1.0f );
1705 
1706         // Right face
1707 
1708         glTexCoord2f( 0.0f, 0.0f );
1709         glVertex3f( 1.00f, -1.0f, -1.0f );
1710         glTexCoord2f( 0.0f, 1.0f );
1711         glVertex3f( 1.00f, -1.0f,  1.0f );
1712         glTexCoord2f( 1.0f, 1.0f );
1713         glVertex3f( 1.00f,  1.0f,  1.0f );
1714         glTexCoord2f( 1.0f, 0.0f );
1715         glVertex3f( 1.00f,  1.0f, -1.0f );
1716 
1717         // Left Face
1718 
1719         glTexCoord2f( 1.0f, 0.0f );
1720         glVertex3f( -1.00f, -1.0f, -1.0f );
1721         glTexCoord2f( 0.0f, 0.0f );
1722         glVertex3f( -1.00f,  1.0f, -1.0f );
1723         glTexCoord2f( 0.0f, 1.0f );
1724         glVertex3f( -1.00f,  1.0f,  1.0f );
1725         glTexCoord2f( 1.0f, 1.0f );
1726         glVertex3f( -1.00f, -1.0f,  1.0f );
1727     }
1728 
1729     glEnd();
1730     glBindTexture(GL_TEXTURE_2D, tb);
1731 
1732     glBegin(GL_QUADS);
1733     {
1734         glColor4d(1.0, 1.0, 1.0, 1.0);
1735 
1736         // Back Face
1737 
1738         glTexCoord2f( 1.0f, 0.0f );
1739         glVertex3f( -1.0f, -1.0f, -1.00f );
1740         glTexCoord2f( 1.0f, 1.0f );
1741         glVertex3f( -1.0f,  1.0f, -1.00f );
1742         glTexCoord2f( 0.0f, 1.0f );
1743         glVertex3f(  1.0f,  1.0f, -1.00f );
1744         glTexCoord2f( 0.0f, 0.0f );
1745         glVertex3f(  1.0f, -1.0f, -1.00f );
1746     }
1747 
1748     glEnd();
1749 
1750     if ((d->i >= rotStart) && (d->i < (tot - rotStart)))
1751     {
1752         xrot += 360.0f / (float)(tot - 2 * rotStart);
1753         yrot += 180.0f / (float)(tot - 2 * rotStart);
1754     }
1755 
1756     d->i++;
1757 }
1758 
1759 void PresentationGL::slotPause()
1760 {
1761     d->timer->stop();
1762     showOverlays();
1763 }
1764 
1765 void PresentationGL::slotPlay()
1766 {
1767     hideOverlays();
1768     slotTimeOut();
1769 }
1770 
1771 void PresentationGL::slotPrev()
1772 {
1773     previousFrame();
1774 
1775     if (d->endOfShow)
1776     {
1777         update();
1778         return;
1779     }
1780 
1781     d->effectRunning = false;
1782 
1783     loadImage();
1784     update();
1785 }
1786 
1787 void PresentationGL::slotNext()
1788 {
1789     advanceFrame();
1790 
1791     if (d->endOfShow)
1792     {
1793         update();
1794         return;
1795     }
1796 
1797     d->effectRunning = false;
1798 
1799     loadImage();
1800     update();
1801 }
1802 
1803 void PresentationGL::slotClose()
1804 {
1805     close();
1806 }
1807 
1808 QPixmap PresentationGL::generateOutlinedTextPixmap(const QString& text)
1809 {
1810     QFont fn(font());
1811     fn.setPointSize(fn.pointSize());
1812     fn.setBold(true);
1813 
1814     return generateOutlinedTextPixmap(text, fn);
1815 }
1816 
1817 QPixmap PresentationGL::generateOutlinedTextPixmap(const QString& text, QFont& fn)
1818 {
1819     QColor fgColor(Qt::white);
1820     QColor bgColor(Qt::black);
1821 
1822     return generateCustomOutlinedTextPixmap(text, fn, fgColor, bgColor, 0, true);
1823 }
1824 
1825 QPixmap PresentationGL::generateCustomOutlinedTextPixmap(const QString& text, QFont& fn,
1826                                                          QColor& fgColor, QColor& bgColor,
1827                                                          int opacity, bool drawTextOutline)
1828 {
1829     QFontMetrics fm(fn);
1830     QRect rect = fm.boundingRect(text);
1831     rect.adjust( -fm.maxWidth(), -fm.height(), fm.maxWidth(), fm.height() / 2 );
1832 
1833     QPixmap pix(rect.width(), rect.height());
1834     pix.fill(Qt::transparent);
1835 
1836     if (opacity > 0)
1837     {
1838         QPainter pbg(&pix);
1839         pbg.setBrush(bgColor);
1840         pbg.setPen(bgColor);
1841         pbg.setOpacity(opacity / 10.0);
1842         pbg.drawRoundedRect(0,                     0,
1843                             (int)pix.width(),      (int)pix.height(),
1844                             (int)pix.height() / 3, (int)pix.height() / 3);
1845     }
1846 
1847     QPainter p(&pix);
1848     p.setRenderHint(QPainter::Antialiasing, true);
1849     p.setBrush(QBrush());
1850     p.setPen(QPen());
1851 
1852     // draw outline
1853 
1854     QPainterPath path;
1855     path.addText(fm.maxWidth(), fm.height() * 1.5, fn, text);
1856 
1857     QPainterPathStroker stroker;
1858     stroker.setWidth(2);
1859     stroker.setCapStyle(Qt::RoundCap);
1860     stroker.setJoinStyle(Qt::RoundJoin);
1861     QPainterPath outline = stroker.createStroke(path);
1862 
1863     if (drawTextOutline)
1864     {
1865         p.fillPath(outline, Qt::black);
1866     }
1867 
1868     p.fillPath(path, QBrush(fgColor));
1869 
1870     p.setRenderHint(QPainter::Antialiasing, false);
1871     p.end();
1872 
1873     return pix;
1874 }
1875 
1876 bool PresentationGL::checkOpenGL() const
1877 {
1878     // No OpenGL context is found. Are the drivers ok?
1879 
1880     if (!isValid())
1881     {
1882         return false;
1883     }
1884 
1885     // GL_EXT_texture3D is not supported
1886 
1887     QString s = QString::fromLatin1(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
1888 
1889     if (!s.contains(QString::fromLatin1("GL_EXT_texture3D"), Qt::CaseInsensitive))
1890     {
1891         return false;
1892     }
1893 
1894     // Everything is ok!
1895 
1896     return true;
1897 }
1898 
1899 } // namespace DigikamGenericPresentationPlugin
1900 
1901 #include "moc_presentationgl.cpp"