1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "PowerOfTwoZoomConstraint.h"
17
18 ZoomLevel
getNearestZoomLevel(ZoomLevel requested,RoundingDirection dir) const19 PowerOfTwoZoomConstraint::getNearestZoomLevel(ZoomLevel requested,
20 RoundingDirection dir) const
21 {
22 int blockSize;
23
24 if (requested.zone == ZoomLevel::FramesPerPixel) {
25 blockSize = getNearestBlockSize(requested.level, dir);
26 if (blockSize > getMaxZoomLevel().level) {
27 blockSize = getMaxZoomLevel().level;
28 }
29 return { requested.zone, blockSize };
30 } else {
31 RoundingDirection opposite = dir;
32 if (dir == RoundUp) opposite = RoundDown;
33 else if (dir == RoundDown) opposite = RoundUp;
34 blockSize = getNearestBlockSize(requested.level, opposite);
35 if (blockSize > getMinZoomLevel().level) {
36 blockSize = getMinZoomLevel().level;
37 }
38 if (blockSize == 1) {
39 return { ZoomLevel::FramesPerPixel, 1 };
40 } else {
41 return { requested.zone, blockSize };
42 }
43 }
44 }
45
46 int
getNearestBlockSize(int req,RoundingDirection dir) const47 PowerOfTwoZoomConstraint::getNearestBlockSize(int req,
48 RoundingDirection dir) const
49 {
50 int max = getMaxZoomLevel().level;
51
52 if (req > max) {
53 return max;
54 }
55
56 for (int bs = 1; bs <= max; bs *= 2) {
57 if (bs < req) {
58 continue;
59 } else if (bs == req) {
60 return bs;
61 } else { // bs > req
62 if (dir == RoundNearest) {
63 if (bs - req < req - bs/2) {
64 return bs;
65 } else {
66 return bs/2;
67 }
68 } else if (dir == RoundDown) {
69 return bs/2;
70 } else {
71 return bs;
72 }
73 }
74 }
75
76 return max;
77 }
78
79