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@929
|
50 int result = 0;
|
Chris@147
|
51
|
Chris@929
|
52 for (int bs = 1; ; bs *= 2) {
|
Chris@1429
|
53 if (bs >= req) {
|
Chris@1429
|
54 if (dir == RoundNearest) {
|
Chris@1429
|
55 if (bs - req < req - bs/2) {
|
Chris@1429
|
56 result = bs;
|
Chris@1429
|
57 break;
|
Chris@1429
|
58 } else {
|
Chris@1429
|
59 result = bs/2;
|
Chris@1429
|
60 break;
|
Chris@1429
|
61 }
|
Chris@1429
|
62 } else if (dir == RoundDown) {
|
Chris@1429
|
63 result = bs/2;
|
Chris@1429
|
64 break;
|
Chris@1429
|
65 } else {
|
Chris@1429
|
66 result = bs;
|
Chris@1429
|
67 break;
|
Chris@1429
|
68 }
|
Chris@1429
|
69 }
|
Chris@147
|
70 }
|
Chris@147
|
71
|
Chris@1324
|
72 if (result > getMaxZoomLevel().level) result = getMaxZoomLevel().level;
|
Chris@147
|
73 return result;
|
Chris@147
|
74 }
|
Chris@147
|
75
|