summaryrefslogtreecommitdiffstats
path: root/src/base/RulerScale.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/RulerScale.cpp')
-rw-r--r--src/base/RulerScale.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/base/RulerScale.cpp b/src/base/RulerScale.cpp
new file mode 100644
index 0000000..510a0a5
--- /dev/null
+++ b/src/base/RulerScale.cpp
@@ -0,0 +1,243 @@
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral right of the authors to claim authorship of this work
+ has been asserted.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#include <cmath>
+#include "RulerScale.h"
+#include "Composition.h"
+
+namespace Rosegarden {
+
+
+//////////////////////////////////////////////////////////////////////
+// RulerScale
+//////////////////////////////////////////////////////////////////////
+
+RulerScale::RulerScale(Composition *c) :
+ m_composition(c)
+{
+ // nothing
+}
+
+RulerScale::~RulerScale()
+{
+ // nothing
+}
+
+int
+RulerScale::getFirstVisibleBar() const
+{
+ return m_composition->getBarNumber(m_composition->getStartMarker());
+}
+
+int
+RulerScale::getLastVisibleBar() const
+{
+ return m_composition->getBarNumber(m_composition->getEndMarker());
+}
+
+double
+RulerScale::getBarWidth(int n) const
+{
+ return getBarPosition(n + 1) - getBarPosition(n);
+}
+
+double
+RulerScale::getBeatWidth(int n) const
+{
+ std::pair<timeT, timeT> barRange = m_composition->getBarRange(n);
+ timeT barDuration = barRange.second - barRange.first;
+ if (barDuration == 0) return 0;
+
+ bool isNew;
+ TimeSignature timeSig = m_composition->getTimeSignatureInBar(n, isNew);
+
+ // cope with partial bars
+ double theoreticalWidth =
+ (getBarWidth(n) * timeSig.getBarDuration()) / barDuration;
+
+ return theoreticalWidth / timeSig.getBeatsPerBar();
+}
+
+int
+RulerScale::getBarForX(double x) const
+{
+ // binary search
+
+ int minBar = getFirstVisibleBar(),
+ maxBar = getLastVisibleBar();
+
+ while (maxBar > minBar) {
+ int middle = minBar + (maxBar - minBar) / 2;
+ if (x > getBarPosition(middle)) minBar = middle + 1;
+ else maxBar = middle;
+ }
+
+ // we've just done equivalent of lower_bound -- we're one bar too
+ // far into the list
+
+ if (minBar > getFirstVisibleBar()) return minBar - 1;
+ else return minBar;
+}
+
+timeT
+RulerScale::getTimeForX(double x) const
+{
+ int n = getBarForX(x);
+
+ double barWidth = getBarWidth(n);
+ std::pair<timeT, timeT> barRange = m_composition->getBarRange(n);
+
+ if (barWidth < 1.0) {
+
+ return barRange.first;
+
+ } else {
+
+ timeT barDuration = barRange.second - barRange.first;
+ x -= getBarPosition(n);
+
+ return barRange.first + (timeT)nearbyint(((double)(x * barDuration) / barWidth));
+ }
+}
+
+double
+RulerScale::getXForTime(timeT time) const
+{
+ int n = m_composition->getBarNumber(time);
+
+ double barWidth = getBarWidth(n);
+ std::pair<timeT, timeT> barRange = m_composition->getBarRange(n);
+ timeT barDuration = barRange.second - barRange.first;
+
+ if (barDuration == 0) {
+
+ return getBarPosition(n);
+
+ } else {
+
+ time -= barRange.first;
+ return getBarPosition(n) + (double)(time * barWidth) / barDuration;
+ }
+}
+
+timeT
+RulerScale::getDurationForWidth(double x, double width) const
+{
+ return getTimeForX(x + width) - getTimeForX(x);
+}
+
+double
+RulerScale::getWidthForDuration(timeT startTime, timeT duration) const
+{
+ return getXForTime(startTime + duration) - getXForTime(startTime);
+}
+
+double
+RulerScale::getTotalWidth() const
+{
+ int n = getLastVisibleBar();
+ return getBarPosition(n) + getBarWidth(n);
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////
+// SimpleRulerScale
+//////////////////////////////////////////////////////////////////////
+
+
+SimpleRulerScale::SimpleRulerScale(Composition *composition,
+ double origin, double ratio) :
+ RulerScale(composition),
+ m_origin(origin),
+ m_ratio(ratio)
+{
+ // nothing
+}
+
+SimpleRulerScale::SimpleRulerScale(const SimpleRulerScale &ruler):
+ RulerScale(ruler.getComposition()),
+ m_origin(ruler.getOrigin()),
+ m_ratio(ruler.getUnitsPerPixel())
+{
+ // nothing
+}
+
+
+SimpleRulerScale::~SimpleRulerScale()
+{
+ // nothing
+}
+
+double
+SimpleRulerScale::getBarPosition(int n) const
+{
+ timeT barStart = m_composition->getBarRange(n).first;
+ return getXForTime(barStart);
+}
+
+double
+SimpleRulerScale::getBarWidth(int n) const
+{
+ std::pair<timeT, timeT> range = m_composition->getBarRange(n);
+ return (double)(range.second - range.first) / m_ratio;
+}
+
+double
+SimpleRulerScale::getBeatWidth(int n) const
+{
+ bool isNew;
+ TimeSignature timeSig(m_composition->getTimeSignatureInBar(n, isNew));
+ return (double)(timeSig.getBeatDuration()) / m_ratio;
+}
+
+int
+SimpleRulerScale::getBarForX(double x) const
+{
+ return m_composition->getBarNumber(getTimeForX(x));
+}
+
+timeT
+SimpleRulerScale::getTimeForX(double x) const
+{
+ timeT t = (timeT)(nearbyint((double)(x - m_origin) * m_ratio));
+
+ int firstBar = getFirstVisibleBar();
+ if (firstBar != 0) {
+ t += m_composition->getBarRange(firstBar).first;
+ }
+
+ return t;
+}
+
+double
+SimpleRulerScale::getXForTime(timeT time) const
+{
+ int firstBar = getFirstVisibleBar();
+ if (firstBar != 0) {
+ time -= m_composition->getBarRange(firstBar).first;
+ }
+
+ return m_origin + (double)time / m_ratio;
+}
+
+
+}