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