On Tuesday 13 January 2009, Marco Martin wrote:
> On Monday 12 January 2009, Aaron J. Seigo wrote:
> > On Monday 12 January 2009, Marco Martin wrote:
> > > if the possible positions are not that much (lets say something like on
> > > the 4 corners) maybe using a single pixmap for caching would still be
> > > possible? or maybe just if the position is consistent across instances
> > > the impact on cache would still be acceptable hmm
> >
> > as long as this is cool with Pinheiro and his artistic vision, a limited
> > # of positions us the best way to go imho. whether that's 4, 6 or 10
> > probably doesn't matter too much.
> >
> > once its in, we can play with tweaking the parameters around.
> >
> > > for the randomness: i would say still indicize in the cache for the
> > > applet name but attach it to random numbers that controls the actual
> > > positioning. the correspondence saved in a config file? like the one
> > > for element rects?
> >
> > another approach is to use a single initially random seed and then just
> > use that always. a random sequence is predictable if you know the first
> > seed ;) or use that and a combination of the applet id and re-seed the
> > generator each time. then we have only two variables max per widget, one
> > of which is shared amongst all the widgets, so really only N+1 variables
> > in total with the N variables already known to us via applet->id(). by
> > reseeding with an initially random number + the id we get a constant set
> > of "random" settings even when widgets are deleted.
>
> hmm, what about simply use applet id as seed and take first 2 sequence
> number for the position?
> would be quite deterministic and prevedible (given an id always the same
> result) but i don't think it would be a problem and could keep things quite
> simple
>
> i'm also experimenting in saving the position on applet config, quite done
> also tthat patch(a bit bigger, changes also in applet.cpp) it would have a
> bit more entropy

and the latter approach is attached :D
(made applet friend of framesvg to avoid a pretty useless new api call)

> Cheers,
> Marco Martin
>
> > the random seed could be generated once and stored in corona->config() in
> > the top-level, in [General], in [Corona] or in [Containments].
> >
> > that means one more int read out of a file we already parse anyways.
> >
> > > (hmm the thing is becoming complex...)
> >
> > hehe.. KISS!


Index: framesvg.cpp
===================================================================
--- framesvg.cpp	(revision 910178)
+++ framesvg.cpp	(working copy)
@@ -19,97 +19,23 @@
  */
 
 #include "framesvg.h"
+#include "private/framesvg_p.h"
 
 #include <QPainter>
 #include <QSize>
 #include <QBitmap>
 #include <QRegion>
 #include <QTimer>
+#include <QCryptographicHash>
 
 #include <kdebug.h>
 
 #include <plasma/theme.h>
+#include <plasma/applet.h>
 
 namespace Plasma
 {
 
-class FrameData
-{
-public:
-    FrameData()
-      : enabledBorders(FrameSvg::AllBorders),
-        frameSize(-1,-1)
-    {
-    }
-
-    FrameData(const FrameData &other)
-      : enabledBorders(other.enabledBorders),
-        frameSize(other.frameSize)
-    {
-    }
-
-    ~FrameData()
-    {
-    }
-
-    FrameSvg::EnabledBorders enabledBorders;
-    QPixmap cachedBackground;
-    QRegion cachedMask;
-    QSizeF frameSize;
-
-    //measures
-    int topHeight;
-    int leftWidth;
-    int rightWidth;
-    int bottomHeight;
-
-    //margins, are equal to the measures by default
-    int topMargin;
-    int leftMargin;
-    int rightMargin;
-    int bottomMargin;
-
-    //size of the svg where the size of the "center"
-    //element is contentWidth x contentHeight
-    bool noBorderPadding : 1;
-    bool stretchBorders : 1;
-    bool tileCenter : 1;
-};
-
-class FrameSvgPrivate
-{
-public:
-    FrameSvgPrivate(FrameSvg *psvg)
-      : q(psvg),
-        cacheAll(false),
-        saveTimer(0)
-    {
-    }
-
-    ~FrameSvgPrivate()
-    {
-        qDeleteAll(frames);
-        frames.clear();
-    }
-
-    void generateBackground(FrameData *frame);
-    void scheduledCacheUpdate();
-    void updateSizes();
-    void updateNeeded();
-    void updateAndSignalSizes();
-
-    Location location;
-    QString prefix;
-
-    FrameSvg *q;
-
-    bool cacheAll : 1;
-    QStringList framesToSave;
-    QTimer *saveTimer;
-
-    QHash<QString, FrameData*> frames;
-};
-
 FrameSvg::FrameSvg(QObject *parent)
     : Svg(parent),
       d(new FrameSvgPrivate(this))
@@ -338,45 +264,50 @@
     }
 }
 
-QRegion FrameSvg::mask() const
+QPixmap FrameSvg::alphaMask() const
 {
     FrameData *frame = d->frames[d->prefix];
 
-    if (frame->cachedMask.isEmpty()) {
-        // ivan: we are testing whether we have the mask prefixed
-        // elements to use for creating the mask.
-        if (hasElement("mask-" + d->prefix + "center")) {
-            QString oldPrefix = d->prefix;
+    if (hasElement("mask-" + d->prefix + "center")) {
+        QString oldPrefix = d->prefix;
 
-            // We are setting the prefix only temporary to generate
-            // the needed mask image
-            d->prefix = "mask-" + oldPrefix;
+        // We are setting the prefix only temporary to generate
+        // the needed mask image
+        d->prefix = "mask-" + oldPrefix;
 
-            if (!d->frames.contains(d->prefix)) {
-                d->frames.insert(d->prefix, new FrameData(*(d->frames[oldPrefix])));
-                d->updateSizes();
-            }
+        if (!d->frames.contains(d->prefix)) {
+            d->frames.insert(d->prefix, new FrameData(*(d->frames[oldPrefix])));
+            d->updateSizes();
+        }
 
-            FrameData *maskFrame = d->frames[d->prefix];
+        FrameData *maskFrame = d->frames[d->prefix];
+        if (maskFrame->cachedBackground.isNull() || maskFrame->frameSize != frame->frameSize ) {
+            maskFrame->frameSize = frame->frameSize;
+            maskFrame->cachedBackground = QPixmap();
+
+            d->generateBackground(maskFrame);
             if (maskFrame->cachedBackground.isNull()) {
-                d->generateBackground(maskFrame);
-                if (maskFrame->cachedBackground.isNull()) {
-                    return QRegion();
-                }
+                return QPixmap();
             }
+        }
 
-            frame->cachedMask = QBitmap(maskFrame->cachedBackground.alphaChannel().createMaskFromColor(Qt::black));
-            d->prefix = oldPrefix;
-        } else {
+        d->prefix = oldPrefix;
+        return maskFrame->cachedBackground;
+    } else {
+        if (frame->cachedBackground.isNull()) {
+            d->generateBackground(frame);
             if (frame->cachedBackground.isNull()) {
-                d->generateBackground(frame);
-                if (frame->cachedBackground.isNull()) {
-                    return QRegion();
-                }
+                return QPixmap();
             }
-            frame->cachedMask = QRegion(QBitmap(frame->cachedBackground.alphaChannel().createMaskFromColor(Qt::black)));
         }
+        return frame->cachedBackground;
     }
+}
+
+QRegion FrameSvg::mask() const
+{
+    FrameData *frame = d->frames[d->prefix];
+    frame->cachedMask = QRegion(QBitmap(alphaMask().alphaChannel().createMaskFromColor(Qt::black)));
     return frame->cachedMask;
 }
 
@@ -423,7 +354,16 @@
         }
     }
 
-    return frame->cachedBackground;
+    //FIXME: composing with overlay each time makes it way slower, also caching another image isn't sooo good...
+    if (!hasElement(d->prefix+"hint-overlay-stretch")) {
+        return frame->cachedBackground;
+    } else {
+        QPixmap final = frame->cachedBackground;
+        QPainter p(&final);
+        d->generateOverlay(frame);
+        p.drawPixmap(QPoint(0,0), frame->cachedOverlay);
+        return final;
+    }
 }
 
 void FrameSvg::paintFrame(QPainter *painter, const QRectF &target, const QRectF &source)
@@ -437,6 +377,11 @@
     }
 
     painter->drawPixmap(target, frame->cachedBackground, source.isValid() ? source : target);
+
+    d->generateOverlay(frame);
+    if (!frame->cachedOverlay.isNull()) {
+        painter->drawPixmap(target, frame->cachedOverlay, source.isValid() ? source : target);
+    }
 }
 
 void FrameSvg::paintFrame(QPainter *painter, const QPointF &pos)
@@ -450,6 +395,11 @@
     }
 
     painter->drawPixmap(pos, frame->cachedBackground);
+
+    d->generateOverlay(frame);
+    if (!frame->cachedOverlay.isNull()) {
+        painter->drawPixmap(pos, frame->cachedOverlay);
+    }
 }
 
 void FrameSvgPrivate::generateBackground(FrameData *frame)
@@ -458,6 +408,7 @@
         return;
     }
 
+
     QString id = QString::fromLatin1("%5_%4_%3_%2_%1_").
                          arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix).arg(q->imagePath());
 
@@ -639,9 +590,54 @@
     saveTimer->start(300);
 }
 
+void FrameSvgPrivate::generateOverlay(FrameData *frame)
+{
+    if (!prefix.startsWith("mask-") && q->hasElement(prefix+"overlay")) {
+        QPoint pos = QPoint(0, 0);
+        QSize overlaySize = q->elementSize(prefix+"overlay");
+
+        //Random pos, stretched and tiled are mutually exclusive
+        if (q->hasElement(prefix+"hint-overlay-random-pos")) {
+            pos = overlayPos;
+        //Stretched or Tiled?
+        } else if (q->hasElement(prefix+"hint-overlay-stretch") || q->hasElement(prefix+"hint-overlay-tile")) {
+            overlaySize = frame->frameSize.toSize();
+        }
+
+        QString id = QString::fromLatin1("overlay_%7_%6_%5_%4_%3_%2_%1_").
+                            arg(overlayPos.y()).arg(overlayPos.x()).arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix).arg(q->imagePath());
+
+        frame->cachedOverlay = QPixmap(frame->frameSize.toSize());
+        frame->cachedOverlay.fill(Qt::transparent);
+        QPainter p(&frame->cachedOverlay);
+
+
+        QPixmap overlay = q->alphaMask();
+
+        QPainter overlayPainter(&overlay);
+        overlayPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
+
+        //Tiling?
+        if (q->hasElement(prefix+"hint-overlay-tile")) {
+            q->resize(q->elementSize(prefix+"overlay"));
+            overlayPainter.drawTiledPixmap(QRect(QPoint(0,0), overlaySize), q->pixmap(prefix+"overlay"));
+            q->resize();
+        } else {
+            q->paint(&overlayPainter, QRect(overlayPos, overlaySize), prefix+"overlay");
+        }
+        overlayPainter.end();
+
+        p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+        p.drawPixmap(overlayPos, overlay, QRect(overlayPos, overlaySize));
+    }
+}
+
+
 void FrameSvgPrivate::scheduledCacheUpdate()
 {
     foreach ( QString prefixToSave, framesToSave) {
+        //insert background
         FrameData *frame = frames[prefix];
         framesToSave.removeAll(prefixToSave);
 
@@ -651,6 +647,12 @@
         //kDebug()<<"Saving to cache frame"<<id;
 
         Theme::defaultTheme()->insertIntoCache(id, frame->cachedBackground);
+
+        //insert overlay
+        id = QString::fromLatin1("overlay_%7_%6_%5_%4_%3_%2_%1_").
+                            arg(overlayPos.y()).arg(overlayPos.x()).arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix).arg(q->imagePath());
+
+        Theme::defaultTheme()->insertIntoCache(id, frame->cachedBackground);
     }
 }
 
Index: applet.h
===================================================================
--- applet.h	(revision 910178)
+++ applet.h	(working copy)
@@ -36,6 +36,7 @@
 #include <plasma/plasma.h>
 #include <plasma/animator.h>
 #include <plasma/version.h>
+#include <plasma/framesvg.h>
 
 class QWidget;
 
@@ -54,6 +55,7 @@
 class ExtenderItem;
 class Package;
 
+
 /**
  * @class Applet plasma/applet.h <Plasma/Applet>
  *
Index: framesvg.h
===================================================================
--- framesvg.h	(revision 910178)
+++ framesvg.h	(working copy)
@@ -76,6 +76,9 @@
 class PLASMA_EXPORT FrameSvg : public Svg
 {
     Q_OBJECT
+
+    friend class Applet;
+
     public:
         /**
          * These flags represents what borders should be drawn
@@ -205,6 +208,11 @@
          */
         Q_INVOKABLE QRegion mask() const;
 
+        /**
+         * @return a pixmap whose alpha channel is the opacity of the frame. It may be the frame itself or a special frame with the mask- prefix
+         */
+        QPixmap alphaMask() const;
+
        /**
         * Sets whether saving all the rendered prefixes in a cache or not
         * @arg cache if use the cache or not
Index: applet.cpp
===================================================================
--- applet.cpp	(revision 910178)
+++ applet.cpp	(working copy)
@@ -73,6 +73,7 @@
 #include "scripting/appletscript.h"
 #include "svg.h"
 #include "framesvg.h"
+#include "private/framesvg_p.h"
 #include "popupapplet.h"
 #include "theme.h"
 #include "view.h"
@@ -123,6 +124,7 @@
     }
 
     setParent(parentObject);
+
     // WARNING: do not access config() OR globalConfig() in this method!
     //          that requires a scene, which is not available at this point
     d->init();
@@ -760,6 +762,16 @@
             setMinimumSize(minimumSize().expandedTo(fitSize));
         }
         d->background->resizeFrame(boundingRect().size());
+
+        d->background->d->overlayPos = config().readEntry("overlayPos", QPoint());
+        if (d->background->d->overlayPos == QPoint()) {
+            qsrand(QDateTime::currentDateTime().toTime_t());
+            QSize overlaySize = d->background->elementSize("overlay");
+            d->background->d->overlayPos.rx() = qrand() % (overlaySize.width() + overlaySize.width()+ 1) - overlaySize.width();
+            d->background->d->overlayPos.ry() = qrand() % (overlaySize.height() + overlaySize.height() + 1) - overlaySize.height();
+            config().writeEntry("overlayPos", d->background->d->overlayPos);
+        }
+
     } else if (d->background) {
         qreal left, top, right, bottom;
         d->background->getMargins(left, top, right, bottom);
Index: private/framesvg_p.h
===================================================================
--- private/framesvg_p.h	(revision 0)
+++ private/framesvg_p.h	(revision 0)
@@ -0,0 +1,111 @@
+/*
+ *   Copyright 2008 by Aaron Seigo <ase...@kde.org>
+ *   Copyright 2008 Marco Martin <notm...@gmail.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef PLASMA_FRAMESVG_P_H
+#define PLASMA_FRAMESVG_P_H
+
+#include <QHash>
+
+namespace Plasma
+{
+class FrameData
+{
+public:
+    FrameData()
+      : enabledBorders(FrameSvg::AllBorders),
+        frameSize(-1,-1)
+    {
+    }
+
+    FrameData(const FrameData &other)
+      : enabledBorders(other.enabledBorders),
+        frameSize(other.frameSize)
+    {
+    }
+
+    ~FrameData()
+    {
+    }
+
+    FrameSvg::EnabledBorders enabledBorders;
+    QPixmap cachedBackground;
+    QPixmap cachedOverlay;
+    QRegion cachedMask;
+    QSizeF frameSize;
+
+    //measures
+    int topHeight;
+    int leftWidth;
+    int rightWidth;
+    int bottomHeight;
+
+    //margins, are equal to the measures by default
+    int topMargin;
+    int leftMargin;
+    int rightMargin;
+    int bottomMargin;
+
+    //size of the svg where the size of the "center"
+    //element is contentWidth x contentHeight
+    bool noBorderPadding : 1;
+    bool stretchBorders : 1;
+    bool tileCenter : 1;
+};
+
+class FrameSvgPrivate
+{
+public:
+    FrameSvgPrivate(FrameSvg *psvg)
+      : q(psvg),
+        cacheAll(false),
+        saveTimer(0),
+        overlayPos(0,0)
+    {
+    }
+
+    ~FrameSvgPrivate()
+    {
+        qDeleteAll(frames);
+        frames.clear();
+    }
+
+    void generateBackground(FrameData *frame);
+    void generateOverlay(FrameData *frame);
+    void scheduledCacheUpdate();
+    void updateSizes();
+    void updateNeeded();
+    void updateAndSignalSizes();
+
+    Location location;
+    QString prefix;
+
+    FrameSvg *q;
+
+    bool cacheAll : 1;
+    QStringList framesToSave;
+    QTimer *saveTimer;
+    QPoint overlayPos;
+
+    QHash<QString, FrameData*> frames;
+};
+
+}
+
+#endif
_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel

Reply via email to