View previous topic :: View next topic 
Author 
Message 
piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Sun Aug 08, 2010 8:11 am Post subject: Patch to smooth KDE minimize/unminimize animation 


Edit  for updated patch, see my post below at Wed Dec 07, 2011 10:38 pm.
Hi. I've made the following patch which seems to make the KDE4 minimize/unminimize animations a little smoother  i.e., less "linear"  when the windows are unminimized, the animation slows down as the windows approach their target size. I remember compiz doing this, and it seemed overall smoother.
Code:   a/kwin/lib/kwineffects.h.old 20100807 22:56:43.000000000 0700
+++ b/kwin/lib/kwineffects.h 20100807 23:01:02.000000000 0700
@@ 460,6 +461,7 @@
**/
static double interpolate(double x, double y, double a)
{
+ a = a * a;
return x * (1  a) + y * a;
}
/** Helper to set WindowPaintData and QRegion to necessary transformations so that 
I'm not a programmer, so this patch may very well break stuff. So far I've had no problems.
The patch can be tweaked, as well, by altering the number of times 'a' is multiplied by itself.
If someone can work out the math to make this even smoother, that would be cool.
The patch applies against kwin of the 4.4.5 variety. You would need to add the following single line (without the '+') to /usr/portage/kdebase/kwin/kwin4.4.5.ebuild:
Code:  PATCHES=(
"${FILESDIR}/${PN}4.4.2xinerama_cmake_automagic.patch"
+ "${FILESDIR}/kwineffects.h.patch"
) 
To be consistent the patch would be saved as kwineffects.h.patch in the /usr/portage/kdebase/kwin/files directory.
And then, of course,
Code:  ebuild kwin4.4.5.ebuild manifest 
Last edited by piwacet on Thu Dec 08, 2011 3:40 am; edited 2 times in total 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Mon Aug 09, 2010 9:42 pm Post subject: 


Reading the comments of kwineffects.h, I am not sure if this function is what you would want to patch. In order to make the window animation smoother, what you would want to do is modify the code to scale the area according to some function. Ideally, this probably should be a linear function to bring the area from some upper limit to some lower limit within the allowed time for the effect, but I imagine that you could use a nonlinear function as well.
If time u is the start of the effect, time v is the end of the effect and t is the current time, then the area should scale according to the function f(t) = ((v  t) / (v  u))^k. Consequently, each dimension of the window will need to be scaled according g(t) = (f(t))^(1/2) or g(t) = ((v  t) / (v  u))^(k/2). This is where k is a tuning variable that can be used to get a linear effect when k = 1, an effect where the transition is slow when the window is large and quick when the window is small when k < 1 and an effect where the transition is quick when the window is small and slow when the window is large when k > 1.
Thinking about it some more, the right place to make this kind of change would be where the value of a is generated, because that is what you would want to replace with the equation g(t) that I provided above. How did you come upon the function that you modified in your patch? kwin is such a large piece of software that I am not sure where I would begin if I wanted to make a change, much less find a spot related to the area like it appears that you have done here. 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Mon Aug 09, 2010 10:37 pm Post subject: 


I found the spot where interpolate() is being called. It is in ./kwin/effects/minimizeanimation/minimizeanimation.cpp. Although I am not quite certain where it is being computed, it appears that a = (v  t) / (v  u). Unfortunately, it appears that each time kwin scales the window, it scales it from the current size, rather than the original size. Unless the value of a is not what I think it is and is being specially changed to counteract this effect, the window scaling will be smooth or laggy depending on the behavior of the kernel scheduler, which in my opinion is a bad way of doing things. To make matters worse, I am not sure where or if the original size of the window is stored and without either that information or how what the scaling factor was used previously on the window coordinates, doing proper window scaling seems impossible. Perhaps this is why KDE's minimization effect always seemed strange to me.
Anyway, I probably could fix this myself if I studied kwin's code more closely, but I think it would be best to file a bug report with upstream. I already described in my previous post how the window scaling should be done. It would probably best if upstream implemented it, because then the k constant could be softcoded to give the user the ability to tune over how the window scaling works from KDE's control panel. I have my own things to do, so I will look into filing a bug report about this later, although it would probably be better if the original poster filed it, because he is the one who pointed out this issue. 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Tue Aug 10, 2010 3:07 am Post subject: 


Thanks so much for looking at this. For anyone who is interested, here are the relevant chunks of code, I believe this is current HEAD (not 4.4.5):
The interpolate() function, in kwineffects.h, at line 513:
http://lxr.kde.org/source/KDE/kdebase/workspace/kwin/lib/kwineffects.h#513
Code:  513 static double interpolate(double x, double y, double a)
514 {
515 return x * (1  a) + y * a;
516 }

And the place where this function is called, in minimizeanimation.cpp, at/after line 81:
http://lxr.kde.org/source/KDE/kdebase/workspace/kwin/effects/minimizeanimation/minimizeanimation.cpp#81
Code:  81 void MinimizeAnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
82 {
83 QHash< EffectWindow*, TimeLine >::const_iterator entry = mTimeLineWindows.constFind(w);
84 if( entry != mTimeLineWindows.constEnd() )
85 {
86 // 0 = not minimized, 1 = fully minimized
87 double progress = entry>value();
88
89 QRect geo = w>geometry();
90 QRect icon = w>iconGeometry();
91 // If there's no icon geometry, minimize to the center of the screen
92 if( !icon.isValid() )
93 icon = QRect( displayWidth() / 2, displayHeight() / 2, 0, 0 );
94
95 data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress);
96 data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress);
97 data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress);
98 data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress);
99 data.opacity *= 0.1 + (1progress)*0.9;
100 }
101
102 // Call the next effect.
103 effects>paintWindow( w, mask, region, data );
104 } 
My understanding of the interpolate() function is that it takes 3 arguments, x, y, and a, and returns a value between x and y. 'a' is a value from 0  1 and represents how far between x and y the return value will be; if a=0 it returns x, if a=1 it returns y, if a=0.5 it returns a value half way between x and y, etc. It seems that 'a' would be the same as 'a = (v  t) / (v  u)' as you have said  based on the linearity of the minimize/unminimize animations as I watch them happen.
In minimizeanimation.cpp, the variable 'progess' is passed to the interpolate() function as the value 'a'. Therefore, 'progress' seems to represent how far along the animation is progressing.
What I observe is that the minimize/unminimize animation is very 'linear.' If a minimized window is unminimized, it expands on the screen at a constant speed, until it appears to stop abruptly when it reaches its target size  it's as if the expanding window "bumps into" the edge of the screen and has to stop expanding. I liked the way I remember compiz doing this  more "parabolic"  i.e., as the window expanded, the animation speed would slow as the window reached it's target size, this seemed smoother.
That's the reason I made the patch to square the variable 'a'. Since 'a' is a number that appears to range from 0 to 1, the square of 'a' will be more parabolic, and still behave correctly for a value of 0 or 1 (still equal 0 or 1). Of course, this may break any other stuff that calls the interpolate() function, if something else does.
I would be much happier with a more proper implementation, ideally with even better math to make the animation even more smooth than squaring 'a' does. Unfortunately I don't understand the code in minimizeanimation.cpp well enough to do this. One thought would be to patch this portion of minimizeanimation.cpp so that it calls an entirely new function to generate the interpolate() value with the mathematical behavior that I would like; this would keep the original interpolate() function intact for any other part of the code that may call it. Perhaps I'll keep plucking away.
Again, thanks so much for taking the time to look at this. 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Thu Aug 26, 2010 2:25 am Post subject: 


piwacet, I did not see your response to this thread until today. I just reread my post and what I said regarding k != 1 makes no sense. When k < 1, the effect will be slow when the window is large and quick when the window is small. When k > 1, the effect will be slow when the window is small and quick when the window is large. With what you are saying, I think you would want k > 1 in the equations I posted above.
Anyway, your patch will likely affect much more than just the minimization animation. It would probably be a good idea for you to inline your changes into the minimizeanimation.cpp file until someone comes up with a better solution. I am somewhat hesitant to do much with this because I do not know if this is still a problem in KDE 4.5.0. Did you ever file a bug report regarding this with upstream? 

Back to top 


Akkara Administrator
Joined: 28 Mar 2006 Posts: 6702 Location: &akkara

Posted: Thu Aug 26, 2010 3:08 am Post subject: 


Just to toss some ideas into the mix:
Here's some other functions that take a parameter from 0..1 that have zero slope at one end or the other (or both):
Zero slope at the a == 0 end: a*a /* this is the formula suggested above */
 1  cos(Pi/2 * a)
Zero slope at the a == 1 end: a * (2  a)
 sin(Pi/2 * a)
Zero slope at both ends: a * a * (3  2*a)
 a = sin(Pi/2 * a); a = a * a; /* this one is so close to the one just above it's hardly worthwhile to use */
Also, sometimes things look nicer visually when they follow a power law. Use one of the formulas above and then follow it up with: a = (pow(2,a)  1) / (2  1);
See if you like that better. Change the 2 to other numbers to push the effect faster toward one end or the other. If the fast end is not at the end it needs to be, use: a = 1  a; a = (pow(2,a)  1) / (2  1); a = 1  a;


Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Thu Aug 26, 2010 4:05 am Post subject: 


The source has two issues in it at the moment. One is that the original window size is not saved between repaints, so each time it repaints, a new window size is calculated from the previous size, which is not the original size. That is a problem because it prevents the animation from behaving according to a specific mathematical formula and gives the animation a bit of randomness that in most cases will make the animation look worse than it should look. It also means that this effect is done slightly differently every time it is executed. The second is that the window animation does not appear to be mathematically defined, but doing that is impossible unless the animation obeys the formulae employed.
I have produced a patch that addresses the first issue. I would have had it address the second issue as well, but when I tried to change the code, I could not understand how the existing code functioned unless data.xScale and data.yScale varied between 0 and 1, which suggested to me that the code determining the calculation of the window's dimensions was elsewhere. While I can likely work around that, that would require a bit of trial and error on my part to verify my assumptions and it is late, so I am only patching the first issue.
Here is the patch for anyone interested:
http://paste.pocoo.org/show/254569/
The first issue I described at the top of this post meant that the animation had an annoying inconsistent jerkiness to it. This patch fixes that. At the same time, it does not address the original poster's issue, which is what I outlined as the second issue at the top of this post.
Akkara, although I have not checked your math, functions that have zero slopes at both ends are ideal for this kind of animation. I will look into implementing such a function tomorrow provided that I find time. 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Sat Aug 28, 2010 12:12 am Post subject: 


I spent several hours today trying to modify the behavior of this effect and my theory as to what various variables meant was incorrect. While I now think that it is possible that my above patch does nothing, I am not able to say that for certain because the documentation on the return value of KWin::EffectWindow::geometry() is nonexistent. The return value could be the geometry before the effect or the geometry during the effect and it is not clear to me which of the two it is. I knew no quick and dirty way of saving messages to a log file, so I tried doing things without logging variable values and with what I know now, that is the first thing I should have done.
I filed a bug report with upstream regarding the documentation issues I encountered:
https://bugs.kde.org/show_bug.cgi?id=249288
I am still waiting for piwacet to file a bug report with upstream regarding the effect, because this is his complaint. 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Sat Aug 28, 2010 9:07 pm Post subject: 


Wow, this thread got resurrected. Thanks everyone for looking at this and for the suggestions.
I would like to try out the new math to see how it runs, and to spend some time reasonably soon playing with this.
I have hesitated to file an upstream bug report because I'm not a computer programmer, and feel like my input would be more on the level of "feature request" as opposed to bug report. Although if a patch that works well does come out of this, maybe I should rethink that.
Let me try to work out a slightly improved or better patch and I'll post back here if I have any success.
Thanks! 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Sat Aug 28, 2010 11:03 pm Post subject: 


Edit  consider just skipping this post and going to my next post with the updated patch.
OK, just a quick update. First of all, in order to not break other things that might call interpolate(), I created a new function interpolate_nonlinear() and added it to kwineffects.h, and then updated minimizeanimation.cpp to call this new function instead. An online search of the current KDE codebase does not reveal any hits for "interpolate_nonlinear" so I think this has successfully isolated this change to this specific place in the code. These are all against KDE4.4.5.
Here are the patches:
Code: 
cat minimizeanimation.cpp.patch
 a/kwin/effects/minimizeanimation/minimizeanimation.cpp.old 20100828 14:54:27.000000000 0700
+++ b/kwin/effects/minimizeanimation/minimizeanimation.cpp 20100828 15:07:06.000000000 0700
@@ 92,10 +92,10 @@
if( !icon.isValid() )
icon = QRect( displayWidth() / 2, displayHeight() / 2, 0, 0 );
 data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress);
 data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress);
 data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress);
 data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress);
+ data.xScale *= interpolate_nonlinear(1.0, icon.width() / (double)geo.width(), progress);
+ data.yScale *= interpolate_nonlinear(1.0, icon.height() / (double)geo.height(), progress);
+ data.xTranslate = (int)interpolate_nonlinear(data.xTranslate, icon.x()  geo.x(), progress);
+ data.yTranslate = (int)interpolate_nonlinear(data.yTranslate, icon.y()  geo.y(), progress);
data.opacity *= 0.1 + (1progress)*0.9;
}

Code:  cat kwineffects.h.patch
 a/kwin/lib/kwineffects.h.old 20100828 15:13:03.000000000 0700
+++ b/kwin/lib/kwineffects.h 20100828 15:18:57.000000000 0700
@@ 462,6 +462,16 @@
{
return x * (1  a) + y * a;
}
+ /**
+ * Nonlinearly interpolates between @p x and @p y.
+ *
+ * Returns @p x when @p a = 0; returns @p y when @p a = 1.
+ **/
+ static double interpolate_nonlinear(double x, double y, double a)
+ {
+ a = a * a;
+ return x * (1  a) + y * a;
+ }
/** Helper to set WindowPaintData and QRegion to necessary transformations so that
* a following drawWindow() would put the window at the requested geometry (useful for thumbnails)
**/ 
As above, these patches will need to be saved in the /usr/portage/kdebase/kwin/files directory, and then the following change to the ebuild (without the '+') /usr/portage/kdebase/kwin/kwin4.4.5.ebuild:
Code:  PATCHES=(
"${FILESDIR}/${PN}4.4.2xinerama_cmake_automagic.patch"
+ "${FILESDIR}/minimizeanimation.cpp.patch"
+ "${FILESDIR}/kwineffects.h.patch"
) 
And finally:
Code:  ebuild kwin4.4.5.ebuild manifest
emerge oneshot kwin 
And then log out and back in again.
Now to play with the math.
Last edited by piwacet on Sun Aug 29, 2010 5:31 am; edited 1 time in total 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Sun Aug 29, 2010 4:20 am Post subject: 


OK, well, a new approach. I think this approach will not break anything, as it only creates two new variables "progress_nonlinear_geometry" and "progress_nonlinear_opacity," and an online search of the KDE code shows these terms are not used anywhere else. The patch works by computing the values "progress_nonlinear_geometry" and "progress_nonlinear_opacity" from the original "progress" variable in a nonlinear way, and then uses these new variables in place of the "progress" variable. This approach only involves patching one file, and although I'm not a programmer, this patch may actually be technically correct.
It uses math from Akkara's post above. I noticed that the animation's linear change in opacity was distracting with the nonlinear geometry changes, so the patch also provides math to tweak the way the opacity changes as the animation progresses. The opacity can be tweaked independently of the geometry.
These functions behave correctly in that they will return 1 if given 1, return 0 if given 0, and if given a value between 0 and 1, they will return a value between 0 and 1. My understanding is that the original "progress" variable is a variable that ranges from 0 to 1. The math can be tweaked as per Akkara's descriptions above. Replacing "progress" with the product "progress*progress" or viceversa in the pow() functions can further tweak the math. Specifically, you would tweak 'n,' and the second parameter of the pow() function. The higher the value of 'n,' the more "nonlinear" the animation will be.
Code:  (pow(n, progress)  1) / (n1) 
or
Code:  (pow(n, progress*progress)  1) / (n1) 
Code:  cat minimizeanimation.cpp.patch
 a/kwin/effects/minimizeanimation/minimizeanimation.cpp.old 20100828 16:57:32.000000000 0700
+++ b/kwin/effects/minimizeanimation/minimizeanimation.cpp 20100828 20:03:54.000000000 0700
@@ 19,6 +19,7 @@
*********************************************************************/
#include "minimizeanimation.h"
+#include <math.h>
namespace KWin
{
@@ 85,6 +86,8 @@
{
// 0 = not minimized, 1 = fully minimized
double progress = entry>value();
+ double progress_nonlinear_geometry;
+ double progress_nonlinear_opacity;
QRect geo = w>geometry();
QRect icon = w>iconGeometry();
@@ 92,11 +95,16 @@
if( !icon.isValid() )
icon = QRect( displayWidth() / 2, displayHeight() / 2, 0, 0 );
 data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress);
 data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress);
 data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress);
 data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress);
 data.opacity *= 0.1 + (1progress)*0.9;
+ progress_nonlinear_geometry = (pow(50, progress*progress)  1) / 49;
+
+ data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress_nonlinear_geometry);
+ data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress_nonlinear_geometry);
+ data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress_nonlinear_geometry);
+ data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress_nonlinear_geometry);
+
+ progress_nonlinear_opacity = (pow(3, progress)  1) / 2;
+
+ data.opacity *= 0.1 + (1progress_nonlinear_opacity)*0.9;
}
// Call the next effect.

Minimize/unminimize is smoother now; perhaps not as smooth as I recall compiz being, but this is the best it's been for me so far.
Again, for anyone who is interested, this is what the original file currently looks like in the 4.4 branch:
http://lxr.kde.org/source/KDE/kdebase/workspace/kwin/effects/minimizeanimation/minimizeanimation.cpp?v=4.4branch
Thanks everybody for your help! 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Sun Aug 29, 2010 9:02 pm Post subject: 


Actually, cubing the variable "progress" instead of squaring it has worthwhile effect as well, i.e changing:
Code:  + progress_nonlinear_geometry = (pow(50, progress*progress)  1) / 49; 
to
Code:  + progress_nonlinear_geometry = (pow(50, progress*progress*progress)  1) / 49; 
not sure which I like better. 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Tue Sep 07, 2010 2:15 am Post subject: 


I'm thinking I may submit this patch upstream, see if there is any interest. I'll link this thread. 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Tue Sep 07, 2010 4:42 am Post subject: 


You are computing (50^(progress^3)  1) / 49. Are you sure that is what you want? 

Back to top 


ppurka Advocate
Joined: 26 Dec 2004 Posts: 3256

Posted: Tue Sep 07, 2010 5:23 am Post subject: 


Shining Arcanine wrote:  You are computing (50^(progress^3)  1) / 49. Are you sure that is what you want?  Here progress is between 0 and 1, so it is not computing really large numbers. _________________ emerge quiet redefined  E17 vids: I, II  Now using kde5  e is unstable :/ 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Tue Sep 07, 2010 6:46 am Post subject: 


Actually the version of the formula that I'm currently using (and like) is:
(50^(progress^2)1)/49
But yes, the math may be too compute intensive and I could easily see developers not liking that. 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Tue Sep 07, 2010 10:46 am Post subject: 


piwacet wrote:  Actually the version of the formula that I'm currently using (and like) is:
(50^(progress^2)1)/49
But yes, the math may be too compute intensive and I could easily see developers not liking that. 
Actually, pow() has O(log(n)) time, so it is not an issue. It uses a method called square and multiply:
http://en.wikipedia.org/wiki/Exponentiation_by_squaring 

Back to top 


Akkara Administrator
Joined: 28 Mar 2006 Posts: 6702 Location: &akkara

Posted: Tue Sep 07, 2010 12:31 pm Post subject: 


This is only true when calculating integer powers using that particular algorithm.
The pow() function is a floatingpoint power: both variables are doubles. It is actually constant time, albeit a relatively large constant. The way it works internally is using logs and exponentials. But it doesn't just call the log() function. More precision is needed to compute an accurate power this way, so there's actually a independent specialpurpose log and exponential in there.
How many distinct values does progress take on? If it is less than 100 or so, it might be best to do this with table lookup. For example, if progress increments by 1/NINCR: Code:  double lookup[NINCR+1]; /* <=== note the "+1": this is important */
....
int idx = round(progress * NINCR);
if(idx < 0  idx > NINCR) {
/* this shouldn't happen  log a diagnostic somehow */
idx = (idx < 0) ? 0 : NINCR;
}
return lookup[idx]; 


Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Tue Sep 07, 2010 8:03 pm Post subject: 


Thanks. I don't know how many distinct values 'progress' takes on; I really don't understand the code that well. I suppose with a lookuptable we could make the animation do exactly as we want, but I wonder if the number of values that 'progress' takes is a constant, or if it is a function of screen size or other settings.
I wonder how this patch would work on an older, slower machine. I wonder what KDE regards as the "minimum requirements" that they are coding for.
I've noticed that other animations include the math.h headers, so there must be somewhat complicated math in those, but perhaps these are the animations not meant to be used on older hardware.
Thanks everybody! 

Back to top 


Shining Arcanine Veteran
Joined: 24 Sep 2009 Posts: 1110

Posted: Wed Sep 08, 2010 12:12 am Post subject: 


Akkara wrote: 
This is only true when calculating integer powers using that particular algorithm.
The pow() function is a floatingpoint power: both variables are doubles. It is actually constant time, albeit a relatively large constant. The way it works internally is using logs and exponentials. But it doesn't just call the log() function. More precision is needed to compute an accurate power this way, so there's actually a independent specialpurpose log and exponential in there.
How many distinct values does progress take on? If it is less than 100 or so, it might be best to do this with table lookup. For example, if progress increments by 1/NINCR: Code:  double lookup[NINCR+1]; /* <=== note the "+1": this is important */
....
int idx = round(progress * NINCR);
if(idx < 0  idx > NINCR) {
/* this shouldn't happen  log a diagnostic somehow */
idx = (idx < 0) ? 0 : NINCR;
}
return lookup[idx]; 

That is only true in C. In C++, pow() is overloaded. Since the exponent being passed to the function is an integer, the integer exponent version is called, which has O(log(n)) time:
http://www.cplusplus.com/reference/clibrary/cmath/pow/
I believe that KDE is written in C++, so these distinctions are important. 

Back to top 


Akkara Administrator
Joined: 28 Mar 2006 Posts: 6702 Location: &akkara

Posted: Wed Sep 08, 2010 1:15 am Post subject: 


Shining Arcanine wrote:  In C++, pow() is overloaded. Since the exponent being passed to the function is an integer, the integer exponent version is called, which has O(log(n)) time:
http://www.cplusplus.com/reference/clibrary/cmath/pow/
I believe that KDE is written in C++, so these distinctions are important. 
It is a good point to bring up.
But in piwacet's expression, Code:  progress_nonlinear_geometry = (pow(50, progress*progress*progress)  1) / 49;  or Code:  progress_nonlinear_geometry = (pow(50, progress*progress)  1) / 49; 
the call to pow is receiving a floatingpoint argument for the exponent. The powerbyrepeated squaring algorithm needs a integer exponent, which this is not. The base is integer but that doesn't help here. I'm quite sure this one's using the internal higherprecision log and exponentiation algorithm. 

Back to top 


piwacet Guru
Joined: 30 Dec 2004 Posts: 486

Posted: Thu Dec 08, 2011 3:38 am Post subject: 


Here's an updated patch for 4.7.3. (I built it using 4.7.4 sources, but it applied to my 4.7.3 without problem  I'm using gentoo stable.) Again, I'm not a programmer, but is working so far:
Code:  cat minimizeanimation.cpp.patch
 kdeworkspace4.7.4/kwin/effects/minimizeanimation/minimizeanimation.cpp 20110520 13:32:07.000000000 0700
+++ kdeworkspace4.7.4/kwin/effects/minimizeanimation/minimizeanimation.cpp.new 20111207 19:08:47.004001054 0800
@@ 20,6 +20,7 @@
#include "minimizeanimation.h"
#include <QtCore/QTimeLine>
+#include <math.h>
namespace KWin
{
@@ 84,6 +85,8 @@
if (entry != mTimeLineWindows.constEnd()) {
// 0 = not minimized, 1 = fully minimized
double progress = entry.value()>currentValue();
+ double progress_nonlinear_geometry;
+ double progress_nonlinear_opacity;
QRect geo = w>geometry();
QRect icon = w>iconGeometry();
@@ 91,12 +94,17 @@
if (!icon.isValid())
icon = QRect(displayWidth() / 2, displayHeight() / 2, 0, 0);
 data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress);
 data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress);
 data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress);
 data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress);
 data.opacity *= 0.1 + (1  progress) * 0.9;
 }
+ progress_nonlinear_geometry = (pow(50, progress*progress)  1) / 49;
+
+ data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress_nonlinear_geometry);
+ data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress_nonlinear_geometry);
+ data.xTranslate = (int)interpolate(data.xTranslate, icon.x()  geo.x(), progress_nonlinear_geometry);
+ data.yTranslate = (int)interpolate(data.yTranslate, icon.y()  geo.y(), progress_nonlinear_geometry);
+
+ progress_nonlinear_opacity = (pow(3, progress)  1) / 2;
+
+ data.opacity *= 0.1 + (1progress_nonlinear_opacity)*0.9;
+}
// Call the next effect.
effects>paintWindow(w, mask, region, data); 


Back to top 




You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum

