Magiclamp: fix integer overflow, cpu waste

BUG: 284738
This commit is contained in:
Thomas Lübking 2011-12-01 01:58:43 +01:00
parent ac3bc1fcef
commit 6355a217c2

View file

@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwinconfig.h> #include <kwinconfig.h>
#include <kconfiggroup.h> #include <kconfiggroup.h>
#include <QtCore/QTimeLine> #include <QtCore/QTimeLine>
#include <QtDebug>
namespace KWin namespace KWin
{ {
@ -114,7 +115,6 @@ void MagicLampEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Win
QRect geo = w->geometry(); QRect geo = w->geometry();
QRect icon = w->iconGeometry(); QRect icon = w->iconGeometry();
QRect area = effects->clientArea(ScreenArea, w);
IconPosition position = Top; IconPosition position = Top;
// If there's no icon geometry, minimize to the center of the screen // If there's no icon geometry, minimize to the center of the screen
if (!icon.isValid()) { if (!icon.isValid()) {
@ -205,108 +205,122 @@ void MagicLampEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Win
} }
} }
#define SANITIZE_PROGRESS if (p_progress[0] < 0)\
p_progress[0] = -p_progress[0];\
if (p_progress[1] < 0)\
p_progress[1] = -p_progress[1]
#define SET_QUADS(_SET_A_, _A_, _DA_, _SET_B_, _B_, _O0_, _O1_, _O2_, _O3_) quad[0]._SET_A_((icon._A_() + icon._DA_()*(quad[0]._A_() / geo._DA_()) - (quad[0]._A_() + geo._A_()))*p_progress[_O0_] + quad[0]._A_());\
quad[1]._SET_A_((icon._A_() + icon._DA_()*(quad[1]._A_() / geo._DA_()) - (quad[1]._A_() + geo._A_()))*p_progress[_O1_] + quad[1]._A_());\
quad[2]._SET_A_((icon._A_() + icon._DA_()*(quad[2]._A_() / geo._DA_()) - (quad[2]._A_() + geo._A_()))*p_progress[_O2_] + quad[2]._A_());\
quad[3]._SET_A_((icon._A_() + icon._DA_()*(quad[3]._A_() / geo._DA_()) - (quad[3]._A_() + geo._A_()))*p_progress[_O3_] + quad[3]._A_());\
\
quad[0]._SET_B_(quad[0]._B_() + offset[_O0_]);\
quad[1]._SET_B_(quad[1]._B_() + offset[_O1_]);\
quad[2]._SET_B_(quad[2]._B_() + offset[_O2_]);\
quad[3]._SET_B_(quad[3]._B_() + offset[_O3_])
WindowQuadList newQuads; WindowQuadList newQuads;
foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach float quadFactor; // defines how fast a quad is vertically moved: y coordinates near to window top are slowed down
if (position == Top || position == Bottom) { // it is used as quadFactor^3/windowHeight^3
// quadFactor defines how fast a quad is vertically moved: y coordinates near to window top are slowed down // quadFactor is the y position of the quad but is changed towards becomming the window height
// it is used as quadFactor^3/windowHeight^3 // by that the factor becomes 1 and has no influence any more
// quadFactor is the y position of the quad but is changed towards becomming the window height float offset[2] = {0,0}; // how far has a quad to be moved? Distance between icon and window multiplied by the progress and by the quadFactor
// by that the factor becomes 1 and has no influence any more float p_progress[2] = {0,0}; // the factor which defines how far the x values have to be changed
float quadFactor; // factor is the current moved y value diveded by the distance between icon and window
// how far has a quad to be moved? Distance between icon and window multiplied by the progress and by the quadFactor WindowQuad lastQuad(WindowQuadError);
float yOffsetTop; lastQuad[0].setX(-1);
float yOffsetBottom; lastQuad[0].setY(-1);
// top and bottom progress is the factor which defines how far the x values have to be changed lastQuad[1].setX(-1);
// factor is the current moved y value diveded by the distance between icon and window lastQuad[1].setY(-1);
float topProgress; lastQuad[2].setX(-1);
float bottomProgress; lastQuad[2].setY(-1);
if (position == Bottom) {
if (position == Bottom) {
float height_cube = float(geo.height()) * float(geo.height()) * float(geo.height());
foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach
if (quad[0].y() != lastQuad[0].y() || quad[2].y() != lastQuad[2].y()) {
quadFactor = quad[0].y() + (geo.height() - quad[0].y()) * progress; quadFactor = quad[0].y() + (geo.height() - quad[0].y()) * progress;
yOffsetTop = (icon.y() + quad[0].y() - geo.y()) * progress * offset[0] = (icon.y() + quad[0].y() - geo.y()) * progress * ((quadFactor * quadFactor * quadFactor) / height_cube);
((quadFactor * quadFactor * quadFactor) / (geo.height() * geo.height() * geo.height()));
quadFactor = quad[2].y() + (geo.height() - quad[2].y()) * progress; quadFactor = quad[2].y() + (geo.height() - quad[2].y()) * progress;
yOffsetBottom = (icon.y() + quad[2].y() - geo.y()) * progress * offset[1] = (icon.y() + quad[2].y() - geo.y()) * progress * ((quadFactor * quadFactor * quadFactor) / height_cube);
((quadFactor * quadFactor * quadFactor) / (geo.height() * geo.height() * geo.height())); p_progress[1] = qMin(offset[1] / (icon.y() + icon.height() - geo.y() - float(quad[2].y())), 1.0f);
topProgress = qMin(yOffsetTop / (icon.y() + icon.height() - geo.y() - (float)(quad[0].y() / geo.height() * geo.height())), 1.0f); p_progress[0] = qMin(offset[0] / (icon.y() + icon.height() - geo.y() - float(quad[0].y())), 1.0f);
bottomProgress = qMin(yOffsetBottom / (icon.y() + icon.height() - geo.y() - (float)(quad[2].y() / geo.height() * geo.height())), 1.0f); } else
} else { lastQuad = quad;
quadFactor = geo.height() - quad[0].y() + (quad[0].y()) * progress;
yOffsetTop = (geo.y() - icon.height() + geo.height() + quad[0].y() - icon.y()) * progress *
((quadFactor * quadFactor * quadFactor) / (geo.height() * geo.height() * geo.height()));
quadFactor = geo.height() - quad[2].y() + (quad[2].y()) * progress;
yOffsetBottom = (geo.y() - icon.height() + geo.height() + quad[2].y() - icon.y()) * progress *
((quadFactor * quadFactor * quadFactor) / (geo.height() * geo.height() * geo.height()));
topProgress = qMin(yOffsetTop / (geo.y() - icon.height() + geo.height() - icon.y() -
(float)((geo.height() - quad[0].y()) / geo.height() * geo.height())), 1.0f);
bottomProgress = qMin(yOffsetBottom / (geo.y() - icon.height() + geo.height() - icon.y() -
(float)((geo.height() - quad[2].y()) / geo.height() * geo.height())), 1.0f);
}
if (position == Top) {
yOffsetTop *= -1;
yOffsetBottom *= -1;
}
if (topProgress < 0)
topProgress *= -1;
if (bottomProgress < 0)
bottomProgress *= -1;
SANITIZE_PROGRESS;
// x values are moved towards the center of the icon // x values are moved towards the center of the icon
quad[0].setX((icon.x() + icon.width()*(quad[0].x() / geo.width()) - (quad[0].x() + geo.x()))*topProgress + quad[0].x()); SET_QUADS(setX, x, width, setY, y, 0,0,1,1);
quad[1].setX((icon.x() + icon.width()*(quad[1].x() / geo.width()) - (quad[1].x() + geo.x()))*topProgress + quad[1].x());
quad[2].setX((icon.x() + icon.width()*(quad[2].x() / geo.width()) - (quad[2].x() + geo.x()))*bottomProgress + quad[2].x());
quad[3].setX((icon.x() + icon.width()*(quad[3].x() / geo.width()) - (quad[3].x() + geo.x()))*bottomProgress + quad[3].x());
quad[0].setY(quad[0].y() + yOffsetTop); newQuads.append(quad);
quad[1].setY(quad[1].y() + yOffsetTop); }
quad[2].setY(quad[2].y() + yOffsetBottom); } else if (position == Top) {
quad[3].setY(quad[3].y() + yOffsetBottom); float height_cube = float(geo.height()) * float(geo.height()) * float(geo.height());
} else { foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach
float quadFactor;
float xOffsetLeft; if (quad[0].y() != lastQuad[0].y() || quad[2].y() != lastQuad[2].y()) {
float xOffsetRight; quadFactor = geo.height() - quad[0].y() + (quad[0].y()) * progress;
float leftProgress; offset[0] = (geo.y() - icon.height() + geo.height() + quad[0].y() - icon.y()) * progress * ((quadFactor * quadFactor * quadFactor) / height_cube);
float rightProgress; quadFactor = geo.height() - quad[2].y() + (quad[2].y()) * progress;
if (position == Right) { offset[1] = (geo.y() - icon.height() + geo.height() + quad[2].y() - icon.y()) * progress * ((quadFactor * quadFactor * quadFactor) / height_cube);
quadFactor = quad[0].x() + (geo.width() - quad[0].x()) * progress; p_progress[0] = qMin(offset[0] / (geo.y() - icon.height() + geo.height() - icon.y() - float(geo.height() - quad[0].y())), 1.0f);
xOffsetLeft = (icon.x() + quad[0].x() - geo.x()) * progress * p_progress[1] = qMin(offset[1] / (geo.y() - icon.height() + geo.height() - icon.y() - float(geo.height() - quad[2].y())), 1.0f);
((quadFactor * quadFactor * quadFactor) / (geo.width() * geo.width() * geo.width())); } else
quadFactor = quad[1].x() + (geo.width() - quad[1].x()) * progress; lastQuad = quad;
xOffsetRight = (icon.x() + quad[1].x() - geo.x()) * progress *
((quadFactor * quadFactor * quadFactor) / (geo.width() * geo.width() * geo.width())); offset[0] = -offset[0];
leftProgress = qMin(xOffsetLeft / (icon.x() + icon.width() - geo.x() - (float)(quad[0].x() / geo.width() * geo.width())), 1.0f); offset[1] = -offset[1];
rightProgress = qMin(xOffsetRight / (icon.x() + icon.width() - geo.x() - (float)(quad[1].x() / geo.width() * geo.width())), 1.0f);
} else { SANITIZE_PROGRESS;
quadFactor = geo.width() - quad[0].x() + (quad[0].x()) * progress; // x values are moved towards the center of the icon
xOffsetLeft = (geo.x() - icon.width() + geo.width() + quad[0].x() - icon.x()) * progress * SET_QUADS(setX, x, width, setY, y, 0,0,1,1);
((quadFactor * quadFactor * quadFactor) / (geo.width() * geo.width() * geo.width()));
quadFactor = geo.width() - quad[1].x() + (quad[1].x()) * progress; newQuads.append(quad);
xOffsetRight = (geo.x() - icon.width() + geo.width() + quad[1].x() - icon.x()) * progress * }
((quadFactor * quadFactor * quadFactor) / (geo.width() * geo.width() * geo.width())); } else if (position == Left) {
leftProgress = qMin(xOffsetLeft / (geo.x() - icon.width() + geo.width() - icon.x() - float width_cube = float(geo.width()) * float(geo.width()) * float(geo.width());
(float)((geo.width() - quad[0].x()) / geo.width() * geo.width())), 1.0f); foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach
rightProgress = qMin(xOffsetRight / (geo.x() - icon.width() + geo.width() - icon.x() -
(float)((geo.width() - quad[1].x()) / geo.width() * geo.width())), 1.0f); if (quad[0].x() != lastQuad[0].x() || quad[1].x() != lastQuad[1].x()) {
} quadFactor = geo.width() - quad[0].x() + (quad[0].x()) * progress;
if (position == Left) { offset[0] = (geo.x() - icon.width() + geo.width() + quad[0].x() - icon.x()) * progress * ((quadFactor * quadFactor * quadFactor) / width_cube);
xOffsetLeft *= -1; quadFactor = geo.width() - quad[1].x() + (quad[1].x()) * progress;
xOffsetRight *= -1; offset[1] = (geo.x() - icon.width() + geo.width() + quad[1].x() - icon.x()) * progress * ((quadFactor * quadFactor * quadFactor) / width_cube);
} p_progress[0] = qMin(offset[0] / (geo.x() - icon.width() + geo.width() - icon.x() - float(geo.width() - quad[0].x())), 1.0f);
if (leftProgress < 0) p_progress[1] = qMin(offset[1] / (geo.x() - icon.width() + geo.width() - icon.x() - float(geo.width() - quad[1].x())), 1.0f);
leftProgress *= -1; } else
if (rightProgress < 0) lastQuad = quad;
rightProgress *= -1;
offset[0] = -offset[0];
quad[0].setY((icon.y() + icon.height()*(quad[0].y() / geo.height()) - (quad[0].y() + geo.y()))*leftProgress + quad[0].y()); offset[1] = -offset[1];
quad[1].setY((icon.y() + icon.height()*(quad[1].y() / geo.height()) - (quad[1].y() + geo.y()))*rightProgress + quad[1].y());
quad[2].setY((icon.y() + icon.height()*(quad[2].y() / geo.height()) - (quad[2].y() + geo.y()))*rightProgress + quad[2].y()); SANITIZE_PROGRESS;
quad[3].setY((icon.y() + icon.height()*(quad[3].y() / geo.height()) - (quad[3].y() + geo.y()))*leftProgress + quad[3].y()); // y values are moved towards the center of the icon
SET_QUADS(setY, y, height, setX, x, 0,1,1,0);
quad[0].setX(quad[0].x() + xOffsetLeft);
quad[1].setX(quad[1].x() + xOffsetRight); newQuads.append(quad);
quad[2].setX(quad[2].x() + xOffsetRight); }
quad[3].setX(quad[3].x() + xOffsetLeft); } else if (position == Right) {
float width_cube = float(geo.width()) * float(geo.width()) * float(geo.width());
foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach
if (quad[0].x() != lastQuad[0].x() || quad[1].x() != lastQuad[1].x()) {
quadFactor = quad[0].x() + (geo.width() - quad[0].x()) * progress;
offset[0] = (icon.x() + quad[0].x() - geo.x()) * progress * ((quadFactor * quadFactor * quadFactor) / width_cube);
quadFactor = quad[1].x() + (geo.width() - quad[1].x()) * progress;
offset[1] = (icon.x() + quad[1].x() - geo.x()) * progress * ((quadFactor * quadFactor * quadFactor) / width_cube);
p_progress[0] = qMin(offset[0] / (icon.x() + icon.width() - geo.x() - float(quad[0].x())), 1.0f);
p_progress[1] = qMin(offset[1] / (icon.x() + icon.width() - geo.x() - float(quad[1].x())), 1.0f);
} else
lastQuad = quad;
SANITIZE_PROGRESS;
// y values are moved towards the center of the icon
SET_QUADS(setY, y, height, setX, x, 0,1,1,0);
newQuads.append(quad);
} }
newQuads.append(quad);
} }
data.quads = newQuads; data.quads = newQuads;
} }