Chris@1528: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1528: Chris@1528: /* Chris@1530: Sonic Visualiser Chris@1530: An audio file viewer and annotation editor. Chris@1530: Centre for Digital Music, Queen Mary, University of London. Chris@1528: Chris@1530: This program is free software; you can redistribute it and/or Chris@1530: modify it under the terms of the GNU General Public License as Chris@1530: published by the Free Software Foundation; either version 2 of the Chris@1530: License, or (at your option) any later version. See the file Chris@1530: COPYING included with this distribution for more information. Chris@1528: */ Chris@1528: Chris@1528: #ifndef TEST_ZOOM_CONSTRAINTS_H Chris@1528: #define TEST_ZOOM_CONSTRAINTS_H Chris@1528: Chris@1528: #include "../PowerOfTwoZoomConstraint.h" Chris@1528: #include "../PowerOfSqrtTwoZoomConstraint.h" Chris@1552: #include "../RelativelyFineZoomConstraint.h" Chris@1528: Chris@1528: #include Chris@1528: #include Chris@1528: #include Chris@1528: Chris@1528: #include Chris@1528: Chris@1528: using namespace std; Chris@1528: Chris@1528: class TestZoomConstraints : public QObject Chris@1528: { Chris@1528: Q_OBJECT Chris@1528: Chris@1552: string roundingName(ZoomConstraint::RoundingDirection dir) { Chris@1552: switch (dir) { Chris@1552: case ZoomConstraint::RoundDown: return "RoundDown"; Chris@1552: case ZoomConstraint::RoundUp: return "RoundUp"; Chris@1552: case ZoomConstraint::RoundNearest: return "RoundNearest"; Chris@1552: } Chris@1552: return ""; Chris@1552: } Chris@1552: Chris@1552: void compare(ZoomLevel zin, Chris@1552: ZoomConstraint::RoundingDirection dir, Chris@1552: ZoomLevel zobt, Chris@1552: ZoomLevel zexp) { Chris@1552: if (zexp.level == 1) { Chris@1552: // A zoom level of "1 pixel per frame" is not considered Chris@1552: // canonical - it should be "1 frame per pixel" Chris@1552: zexp.zone = ZoomLevel::FramesPerPixel; Chris@1552: } Chris@1552: if (zobt == zexp) { Chris@1552: return; Chris@1552: } else { Chris@1552: cerr << "For input " << zin << " and rounding direction " Chris@1552: << roundingName(dir) Chris@1552: << ", expected output " << zexp << " but obtained " << zobt Chris@1552: << endl; Chris@1552: QCOMPARE(zobt, zexp); Chris@1552: } Chris@1552: } Chris@1552: Chris@1531: void checkFpp(const ZoomConstraint &c, Chris@1531: ZoomConstraint::RoundingDirection dir, Chris@1531: int n, Chris@1531: int expected) { Chris@1552: ZoomLevel zin(ZoomLevel::FramesPerPixel, n); Chris@1552: ZoomLevel zexp(ZoomLevel::FramesPerPixel, expected); Chris@1552: ZoomLevel zobt(c.getNearestZoomLevel(zin, dir)); Chris@1552: compare(zin, dir, zobt, zexp); Chris@1531: } Chris@1552: Chris@1552: void checkPpf(const ZoomConstraint &c, Chris@1552: ZoomConstraint::RoundingDirection dir, Chris@1552: int n, Chris@1552: int expected) { Chris@1552: ZoomLevel zin(ZoomLevel::PixelsPerFrame, n); Chris@1552: ZoomLevel zexp(ZoomLevel::PixelsPerFrame, expected); Chris@1552: ZoomLevel zobt(c.getNearestZoomLevel(zin, dir)); Chris@1552: compare(zin, dir, zobt, zexp); Chris@1552: } Chris@1552: Chris@1552: void checkBoth(const ZoomConstraint &c, Chris@1552: ZoomConstraint::RoundingDirection dir, Chris@1552: int n, Chris@1552: int expected) { Chris@1552: checkFpp(c, dir, n, expected); Chris@1552: checkPpf(c, dir, n, expected); Chris@1552: } Chris@1552: Chris@1552: void checkMaxMin(const ZoomConstraint &c, Chris@1552: ZoomConstraint::RoundingDirection dir) { Chris@1552: auto max = c.getMaxZoomLevel(); Chris@1552: compare(max, dir, Chris@1552: c.getNearestZoomLevel(max, dir), max); Chris@1552: compare(max.incremented(), dir, Chris@1552: c.getNearestZoomLevel(max.incremented(), dir), max); Chris@1552: auto min = c.getMinZoomLevel(); Chris@1552: compare(min, dir, Chris@1552: c.getNearestZoomLevel(min, dir), min); Chris@1552: compare(min.decremented(), dir, Chris@1552: c.getNearestZoomLevel(min.decremented(), dir), min); Chris@1552: } Chris@1552: Chris@1552: const static ZoomConstraint::RoundingDirection up = ZoomConstraint::RoundUp; Chris@1552: const static ZoomConstraint::RoundingDirection down = ZoomConstraint::RoundDown; Chris@1552: const static ZoomConstraint::RoundingDirection nearest = ZoomConstraint::RoundNearest; Chris@1552: Chris@1528: private slots: Chris@1528: void unconstrainedNearest() { Chris@1528: ZoomConstraint c; Chris@1552: checkBoth(c, nearest, 1, 1); Chris@1552: checkBoth(c, nearest, 2, 2); Chris@1552: checkBoth(c, nearest, 3, 3); Chris@1552: checkBoth(c, nearest, 4, 4); Chris@1552: checkBoth(c, nearest, 20, 20); Chris@1552: checkBoth(c, nearest, 32, 32); Chris@1530: auto max = c.getMaxZoomLevel(); Chris@1530: QCOMPARE(c.getNearestZoomLevel(max), max); Chris@1531: QCOMPARE(c.getNearestZoomLevel(max.incremented()), max); Chris@1528: } Chris@1528: Chris@1528: void unconstrainedUp() { Chris@1528: ZoomConstraint c; Chris@1552: checkBoth(c, up, 1, 1); Chris@1552: checkBoth(c, up, 2, 2); Chris@1552: checkBoth(c, up, 3, 3); Chris@1552: checkBoth(c, up, 4, 4); Chris@1552: checkBoth(c, up, 20, 20); Chris@1552: checkBoth(c, up, 32, 32); Chris@1530: auto max = c.getMaxZoomLevel(); Chris@1552: QCOMPARE(c.getNearestZoomLevel(max, up), max); Chris@1552: QCOMPARE(c.getNearestZoomLevel(max.incremented(), up), max); Chris@1528: } Chris@1528: Chris@1528: void unconstrainedDown() { Chris@1528: ZoomConstraint c; Chris@1552: checkBoth(c, down, 1, 1); Chris@1552: checkBoth(c, down, 2, 2); Chris@1552: checkBoth(c, down, 3, 3); Chris@1552: checkBoth(c, down, 4, 4); Chris@1552: checkBoth(c, down, 20, 20); Chris@1552: checkBoth(c, down, 32, 32); Chris@1530: auto max = c.getMaxZoomLevel(); Chris@1552: QCOMPARE(c.getNearestZoomLevel(max, down), max); Chris@1552: QCOMPARE(c.getNearestZoomLevel(max.incremented(), down), max); Chris@1528: } Chris@1528: Chris@1528: void powerOfTwoNearest() { Chris@1528: PowerOfTwoZoomConstraint c; Chris@1552: checkBoth(c, nearest, 1, 1); Chris@1552: checkBoth(c, nearest, 2, 2); Chris@1552: checkBoth(c, nearest, 3, 2); Chris@1552: checkBoth(c, nearest, 4, 4); Chris@1552: checkBoth(c, nearest, 20, 16); Chris@1552: checkBoth(c, nearest, 23, 16); Chris@1552: checkBoth(c, nearest, 24, 16); Chris@1552: checkBoth(c, nearest, 25, 32); Chris@1530: auto max = c.getMaxZoomLevel(); Chris@1530: QCOMPARE(c.getNearestZoomLevel(max), max); Chris@1531: QCOMPARE(c.getNearestZoomLevel(max.incremented()), max); Chris@1528: } Chris@1528: Chris@1528: void powerOfTwoUp() { Chris@1528: PowerOfTwoZoomConstraint c; Chris@1552: checkBoth(c, up, 1, 1); Chris@1552: checkBoth(c, up, 2, 2); Chris@1552: checkFpp(c, up, 3, 4); Chris@1552: checkPpf(c, up, 3, 2); Chris@1552: checkBoth(c, up, 4, 4); Chris@1552: checkFpp(c, up, 20, 32); Chris@1552: checkPpf(c, up, 20, 16); Chris@1552: checkBoth(c, up, 32, 32); Chris@1552: checkFpp(c, up, 33, 64); Chris@1552: checkPpf(c, up, 33, 32); Chris@1552: checkMaxMin(c, up); Chris@1528: } Chris@1528: Chris@1528: void powerOfTwoDown() { Chris@1528: PowerOfTwoZoomConstraint c; Chris@1552: checkBoth(c, down, 1, 1); Chris@1552: checkBoth(c, down, 2, 2); Chris@1552: checkFpp(c, down, 3, 2); Chris@1552: checkPpf(c, down, 3, 4); Chris@1552: checkBoth(c, down, 4, 4); Chris@1552: checkFpp(c, down, 20, 16); Chris@1552: checkPpf(c, down, 20, 32); Chris@1552: checkBoth(c, down, 32, 32); Chris@1552: checkFpp(c, down, 33, 32); Chris@1552: checkPpf(c, down, 33, 64); Chris@1552: checkMaxMin(c, down); Chris@1528: } Chris@1528: Chris@1528: void powerOfSqrtTwoNearest() { Chris@1528: PowerOfSqrtTwoZoomConstraint c; Chris@1552: checkBoth(c, nearest, 1, 1); Chris@1552: checkBoth(c, nearest, 2, 2); Chris@1552: checkBoth(c, nearest, 3, 2); Chris@1552: checkBoth(c, nearest, 4, 4); Chris@1552: checkBoth(c, nearest, 18, 16); Chris@1552: checkBoth(c, nearest, 19, 16); Chris@1552: checkBoth(c, nearest, 20, 22); Chris@1552: checkBoth(c, nearest, 23, 22); Chris@1552: checkBoth(c, nearest, 28, 32); Chris@1528: // PowerOfSqrtTwoZoomConstraint makes an effort to ensure Chris@1528: // bigger numbers get rounded to a multiple of something Chris@1528: // simple (64 or 90 depending on whether they are power-of-two Chris@1528: // or power-of-sqrt-two types) Chris@1552: checkBoth(c, nearest, 350, 360); Chris@1552: // The most extreme level available in ppf mode Chris@1552: // (getMinZoomLevel()) is currently 512, so these bigger Chris@1552: // numbers will only happen in fpp mode Chris@1552: checkFpp(c, nearest, 800, 720); Chris@1552: checkFpp(c, nearest, 1023, 1024); Chris@1552: checkFpp(c, nearest, 1024, 1024); Chris@1552: checkFpp(c, nearest, 1024, 1024); Chris@1552: checkFpp(c, nearest, 1025, 1024); Chris@1552: checkPpf(c, nearest, 800, 512); Chris@1552: checkPpf(c, nearest, 1025, 512); Chris@1552: checkMaxMin(c, nearest); Chris@1528: } Chris@1528: Chris@1528: void powerOfSqrtTwoUp() { Chris@1528: PowerOfSqrtTwoZoomConstraint c; Chris@1552: checkBoth(c, up, 1, 1); Chris@1552: checkBoth(c, up, 2, 2); Chris@1552: checkFpp(c, up, 3, 4); Chris@1552: checkPpf(c, up, 3, 2); Chris@1552: checkBoth(c, up, 4, 4); Chris@1552: checkFpp(c, up, 18, 22); Chris@1552: checkPpf(c, up, 18, 16); Chris@1552: checkBoth(c, up, 22, 22); Chris@1552: checkFpp(c, up, 23, 32); Chris@1552: checkPpf(c, up, 23, 22); Chris@1552: // see comments above Chris@1552: checkFpp(c, up, 800, 1024); Chris@1552: checkFpp(c, up, 1023, 1024); Chris@1552: checkFpp(c, up, 1024, 1024); Chris@1552: checkFpp(c, up, 1025, 1440); Chris@1552: checkPpf(c, up, 300, 256); Chris@1552: checkPpf(c, up, 800, 512); Chris@1552: checkPpf(c, up, 1600, 512); Chris@1552: checkMaxMin(c, up); Chris@1528: } Chris@1528: Chris@1528: void powerOfSqrtTwoDown() { Chris@1528: PowerOfSqrtTwoZoomConstraint c; Chris@1552: checkBoth(c, down, 1, 1); Chris@1552: checkBoth(c, down, 2, 2); Chris@1552: checkFpp(c, down, 3, 2); Chris@1552: checkPpf(c, down, 3, 4); Chris@1552: checkBoth(c, down, 4, 4); Chris@1552: checkFpp(c, down, 18, 16); Chris@1552: checkPpf(c, down, 18, 22); Chris@1552: checkBoth(c, down, 22, 22); Chris@1552: checkFpp(c, down, 23, 22); Chris@1552: checkPpf(c, down, 23, 32); Chris@1552: // see comments above Chris@1552: checkFpp(c, down, 800, 720); Chris@1552: checkFpp(c, down, 1023, 720); Chris@1552: checkFpp(c, down, 1024, 1024); Chris@1552: checkFpp(c, down, 1025, 1024); Chris@1552: checkPpf(c, down, 300, 360); Chris@1552: checkPpf(c, down, 800, 512); Chris@1552: checkPpf(c, down, 1600, 512); Chris@1552: checkMaxMin(c, down); Chris@1552: } Chris@1552: Chris@1552: void relativelyFineNearest() { Chris@1552: RelativelyFineZoomConstraint c; Chris@1552: checkBoth(c, nearest, 1, 1); Chris@1552: checkBoth(c, nearest, 2, 2); Chris@1552: checkBoth(c, nearest, 3, 3); Chris@1552: checkBoth(c, nearest, 4, 4); Chris@1552: checkBoth(c, nearest, 20, 20); Chris@1552: checkBoth(c, nearest, 33, 32); Chris@1552: checkBoth(c, nearest, 59, 56); Chris@1552: checkBoth(c, nearest, 69, 72); Chris@1552: checkBoth(c, nearest, 121, 128); Chris@1552: checkMaxMin(c, nearest); Chris@1552: } Chris@1552: Chris@1552: void relativelyFineUp() { Chris@1552: RelativelyFineZoomConstraint c; Chris@1552: checkBoth(c, up, 1, 1); Chris@1552: checkBoth(c, up, 2, 2); Chris@1552: checkBoth(c, up, 3, 3); Chris@1552: checkBoth(c, up, 4, 4); Chris@1552: checkBoth(c, up, 20, 20); Chris@1552: checkFpp(c, up, 33, 36); Chris@1552: checkPpf(c, up, 33, 32); Chris@1552: checkFpp(c, up, 59, 64); Chris@1552: checkPpf(c, up, 59, 56); Chris@1552: checkFpp(c, up, 69, 72); Chris@1552: checkPpf(c, up, 69, 64); Chris@1552: checkFpp(c, up, 121, 128); Chris@1552: checkPpf(c, up, 121, 112); Chris@1552: checkMaxMin(c, up); Chris@1552: } Chris@1552: Chris@1552: void relativelyFineDown() { Chris@1552: RelativelyFineZoomConstraint c; Chris@1552: checkBoth(c, down, 1, 1); Chris@1552: checkBoth(c, down, 2, 2); Chris@1552: checkBoth(c, down, 3, 3); Chris@1552: checkBoth(c, down, 4, 4); Chris@1552: checkBoth(c, down, 20, 20); Chris@1552: checkFpp(c, down, 33, 32); Chris@1552: checkPpf(c, down, 33, 36); Chris@1552: checkFpp(c, down, 59, 56); Chris@1552: checkPpf(c, down, 59, 64); Chris@1552: checkFpp(c, down, 69, 64); Chris@1552: checkPpf(c, down, 69, 72); Chris@1552: checkFpp(c, down, 121, 112); Chris@1552: checkPpf(c, down, 121, 128); Chris@1552: checkMaxMin(c, down); Chris@1528: } Chris@1528: }; Chris@1528: Chris@1528: #endif Chris@1528: