You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
5.3 KiB
244 lines
5.3 KiB
|
|
/*
|
|
Rosegarden
|
|
A sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <bownie@bownie.com>
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
}
|