/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Rosegarden
A MIDI and audio 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 < richard . bown @ ferventsoftware . com >
The moral rights of Guillaume Laurent , Chris Cannam , and Richard
Bown to claim authorship of this work have been asserted .
Other copyrights also apply to some parts of this work . Please
see the AUTHORS file and individual file headers for details .
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 "NotationVLayout.h"
# include "misc/Debug.h"
# include <klocale.h>
# include "base/Composition.h"
# include "base/Event.h"
# include "base/LayoutEngine.h"
# include "base/NotationRules.h"
# include "base/NotationTypes.h"
# include "base/NotationQuantizer.h"
# include "base/Staff.h"
# include "gui/general/ProgressReporter.h"
# include "gui/editors/guitar/Chord.h"
# include "NotationChord.h"
# include "NotationElement.h"
# include "NotationProperties.h"
# include "NotationStaff.h"
# include "NotePixmapFactory.h"
# include <kmessagebox.h>
# include <tqobject.h>
# include <tqstring.h>
# include <tqwidget.h>
namespace Rosegarden
{
using namespace BaseProperties ;
NotationVLayout : : NotationVLayout ( Composition * c , NotePixmapFactory * npf ,
const NotationProperties & properties ,
TQObject * parent , const char * name ) :
ProgressReporter ( parent , name ) ,
m_composition ( c ) ,
m_npf ( npf ) ,
m_notationQuantizer ( c - > getNotationQuantizer ( ) ) ,
m_properties ( properties )
{
// empty
}
NotationVLayout : : ~ NotationVLayout ( )
{
// empty
}
NotationVLayout : : SlurList &
NotationVLayout : : getSlurList ( Staff & staff )
{
SlurListMap : : iterator i = m_slurs . find ( & staff ) ;
if ( i = = m_slurs . end ( ) ) {
m_slurs [ & staff ] = SlurList ( ) ;
}
return m_slurs [ & staff ] ;
}
void
NotationVLayout : : reset ( )
{
m_slurs . clear ( ) ;
}
void
NotationVLayout : : resetStaff ( Staff & staff , timeT , timeT )
{
getSlurList ( staff ) . clear ( ) ;
}
void
NotationVLayout : : scanStaff ( Staff & staffBase , timeT , timeT )
{
START_TIMING ;
NotationStaff & staff = dynamic_cast < NotationStaff & > ( staffBase ) ;
NotationElementList * notes = staff . getViewElementList ( ) ;
NotationElementList : : iterator from = notes - > begin ( ) ;
NotationElementList : : iterator to = notes - > end ( ) ;
NotationElementList : : iterator i ;
for ( i = from ; i ! = to ; + + i ) {
NotationElement * el = static_cast < NotationElement * > ( * i ) ;
// Displaced Y will only be used for certain events -- in
// particular not for notes, whose y-coord is obviously kind
// of meaningful.
double displacedY = 0.0 ;
long dyRaw = 0 ;
el - > event ( ) - > get < Int > ( DISPLACED_Y , dyRaw ) ;
displacedY = double ( dyRaw * m_npf - > getLineSpacing ( ) ) / 1000.0 ;
el - > setLayoutY ( staff . getLayoutYForHeight ( - 9 ) + displacedY ) ;
if ( el - > isRest ( ) ) {
// rests for notes longer than the minim have hotspots
// aligned with the line above the middle line; the rest
// are aligned with the middle line
long noteType ;
bool hasNoteType = el - > event ( ) - > get
< Int > ( NOTE_TYPE , noteType ) ;
if ( hasNoteType & & noteType > Note : : Minim ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( 6 ) + displacedY ) ;
} else {
el - > setLayoutY ( staff . getLayoutYForHeight ( 4 ) + displacedY ) ;
}
// Fix for bug 1090767 Rests outside staves have wrong glyphs
// by William <rosegarden4c AT orthoset.com>
// We use a "rest-outside-stave" glyph for any minim/semibreve/breve
// rest that has been displaced vertically e.g. by fine-positioning
// outside the stave. For small vertical displacements that keep
// the rest inside the stave, we use the "rest-inside-stave" glyph
// and also discretise the displacement into multiples of the
// stave-line spacing. The outside-stave glyphs match the character
// numbers 1D13A, 1D13B and 1D13C in the Unicode 4.0 standard.
if ( hasNoteType & & ( displacedY > 0.1 | | displacedY < - 0.1 ) ) {
// a fiddly check for transition from inside to outside:
int min = - 1 , max = 1 ;
switch ( noteType ) {
case Note : : Breve :
min = - 1 ;
max = 2 ;
break ;
case Note : : Semibreve :
min = - 1 ;
max = 3 ;
break ;
case Note : : Minim :
min = - 2 ;
max = 2 ;
break ;
case Note : : Crotchet :
min = - 1 ;
max = 3 ;
break ;
case Note : : Quaver :
min = - 2 ;
max = 3 ;
break ;
case Note : : Semiquaver :
min = - 3 ;
max = 3 ;
break ;
case Note : : Demisemiquaver :
min = - 3 ;
max = 4 ;
break ;
case Note : : Hemidemisemiquaver :
min = - 4 ;
max = 4 ;
break ;
}
bool outside = false ;
if ( noteType = = Note : : Breve ) {
if ( nearbyint ( displacedY ) < min * m_npf - > getLineSpacing ( ) | |
nearbyint ( displacedY ) > max * m_npf - > getLineSpacing ( ) ) {
outside = true ;
}
} else {
if ( ( int ) displacedY < min * m_npf - > getLineSpacing ( ) | |
( int ) displacedY > max * m_npf - > getLineSpacing ( ) ) {
outside = true ;
}
}
el - > event ( ) - > setMaybe < Bool > ( m_properties . REST_OUTSIDE_STAVE ,
outside ) ;
if ( ! outside ) {
displacedY = ( double ) m_npf - > getLineSpacing ( ) *
( int ( nearbyint ( ( double ) displacedY /
m_npf - > getLineSpacing ( ) ) ) ) ;
if ( noteType > Note : : Minim )
el - > setLayoutY ( staff . getLayoutYForHeight ( 6 ) + displacedY ) ;
else
el - > setLayoutY ( staff . getLayoutYForHeight ( 4 ) + displacedY ) ;
}
// if (displacedY != 0.0)
// NOTATION_DEBUG << "REST_OUTSIDE_STAVE AFTER "
// << " : displacedY : " << displacedY
// << " line-spacing : " << m_npf->getLineSpacing()
// << " time : " << (el->getViewAbsoluteTime())
// << endl;
} else {
el - > event ( ) - > setMaybe < Bool > ( m_properties . REST_OUTSIDE_STAVE ,
false ) ;
}
} else if ( el - > isNote ( ) ) {
NotationChord chord ( * notes , i , m_notationQuantizer , m_properties ) ;
if ( chord . size ( ) = = 0 )
continue ;
std : : vector < int > h ;
for ( unsigned int j = 0 ; j < chord . size ( ) ; + + j ) {
long height = 0 ;
if ( ! ( * chord [ j ] ) - > event ( ) - > get
< Int >
( m_properties . HEIGHT_ON_STAFF , height ) ) {
std : : cerr < < TQString ( " ERROR: Event in chord at %1 has no HEIGHT_ON_STAFF property! \n This is a bug (the program would previously have crashed by now) " ) . arg ( ( * chord [ j ] ) - > getViewAbsoluteTime ( ) ) < < std : : endl ;
( * chord [ j ] ) - > event ( ) - > dump ( std : : cerr ) ;
}
h . push_back ( height ) ;
}
bool stemmed = chord . hasStem ( ) ;
bool stemUp = chord . hasStemUp ( ) ;
bool hasNoteHeadShifted = chord . hasNoteHeadShifted ( ) ;
unsigned int flaggedNote = ( stemUp ? chord . size ( ) - 1 : 0 ) ;
bool hasShifted = chord . hasNoteHeadShifted ( ) ;
double y0 = - 1E50 ; // A very unlikely Y layout value
for ( unsigned int j = 0 ; j < chord . size ( ) ; + + j ) {
el = static_cast < NotationElement * > ( * chord [ j ] ) ;
el - > setLayoutY ( staff . getLayoutYForHeight ( h [ j ] ) ) ;
// Look for collision
const double eps = 0.001 ;
Event * eel = el - > event ( ) ;
double y = el - > getLayoutY ( ) ;
if ( eel - > has ( " pitch " ) ) {
el - > setIsColliding ( fabs ( y - y0 ) < eps ) ;
y0 = y ;
}
// These calculations and assignments are pretty much final
// if the chord is not in a beamed group, but if it is then
// they will be reworked by NotationGroup::applyBeam, which
// is called from NotationHLayout::layout, which is called
// after this. Any inaccuracies here for beamed groups
// should be stamped out there.
// el->event()->setMaybe<Bool>(STEM_UP, stemUp);
el - > event ( ) - > setMaybe < Bool > ( m_properties . VIEW_LOCAL_STEM_UP , stemUp ) ;
bool primary =
( ( stemmed & & stemUp ) ? ( j = = 0 ) : ( j = = chord . size ( ) - 1 ) ) ;
el - > event ( ) - > setMaybe < Bool >
( m_properties . CHORD_PRIMARY_NOTE , primary ) ;
if ( primary ) {
el - > event ( ) - > setMaybe < Int >
( m_properties . CHORD_MARK_COUNT , chord . getMarkCountForChord ( ) ) ;
}
bool shifted = chord . isNoteHeadShifted ( chord [ j ] ) ;
el - > event ( ) - > setMaybe < Bool >
( m_properties . NOTE_HEAD_SHIFTED , shifted ) ;
el - > event ( ) - > setMaybe < Bool >
( m_properties . NOTE_DOT_SHIFTED , false ) ;
if ( hasShifted & & stemUp ) {
long dots = 0 ;
( void ) el - > event ( ) - > get
< Int > ( NOTE_DOTS , dots ) ;
if ( dots > 0 ) {
el - > event ( ) - > setMaybe < Bool >
( m_properties . NOTE_DOT_SHIFTED , true ) ;
}
}
el - > event ( ) - > setMaybe < Bool >
( m_properties . NEEDS_EXTRA_SHIFT_SPACE ,
hasNoteHeadShifted & & ! stemUp ) ;
el - > event ( ) - > setMaybe < Bool >
( m_properties . DRAW_FLAG , j = = flaggedNote ) ;
int stemLength = - 1 ;
if ( j ! = flaggedNote ) {
stemLength = staff . getLayoutYForHeight ( h [ flaggedNote ] ) -
staff . getLayoutYForHeight ( h [ j ] ) ;
if ( stemLength < 0 )
stemLength = - stemLength ;
// NOTATION_DEBUG << "Setting stem length to "
// << stemLength << endl;
} else {
int minStemLength = stemLength ;
if ( h [ j ] < - 2 & & stemUp ) {
//!!! needs tuning, & applying for beamed stems too
minStemLength = staff . getLayoutYForHeight ( h [ j ] ) -
staff . getLayoutYForHeight ( 4 ) ;
} else if ( h [ j ] > 10 & & ! stemUp ) {
minStemLength = staff . getLayoutYForHeight ( 4 ) -
staff . getLayoutYForHeight ( h [ j ] ) ;
}
stemLength = std : : max ( minStemLength , stemLength ) ;
}
el - > event ( ) - > setMaybe < Int >
( m_properties . UNBEAMED_STEM_LENGTH , stemLength ) ;
}
// #938545 (Broken notation: Duplicated note can float
// outside stave) -- Need to cope with the case where a
// note that's not a member of a chord (different stem
// direction &c) falls between notes that are members.
// Not optimal, as we can end up scanning the chord
// multiple times (we'll return to it after scanning the
// contained note). [We can't just iterate over all
// elements within the chord (as we can in hlayout)
// because we need them in height order.]
i = chord . getFirstElementNotInChord ( ) ;
if ( i = = notes - > end ( ) )
i = chord . getFinalElement ( ) ;
else
- - i ;
} else {
if ( el - > event ( ) - > isa ( Clef : : EventType ) ) {
// clef pixmaps have the hotspot placed to coincide
// with the pitch of the clef -- so the alto clef
// should be "on" the middle line, the treble clef
// "on" the line below the middle, etc
el - > setLayoutY ( staff . getLayoutYForHeight
( Clef ( * el - > event ( ) ) . getAxisHeight ( ) ) ) ;
} else if ( el - > event ( ) - > isa ( Rosegarden : : Key : : EventType ) ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( 12 ) ) ;
} else if ( el - > event ( ) - > isa ( Text : : EventType ) ) {
std : : string type = Text : : UnspecifiedType ;
el - > event ( ) - > get < String > ( Text : : TextTypePropertyName , type ) ;
if ( type = = Text : : Dynamic | |
type = = Text : : LocalDirection | |
type = = Text : : UnspecifiedType ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( - 7 ) + displacedY ) ;
} else if ( type = = Text : : Lyric ) {
long verse = 0 ;
el - > event ( ) - > get < Int > ( Text : : LyricVersePropertyName , verse ) ;
el - > setLayoutY ( staff . getLayoutYForHeight ( - 10 - 3 * verse ) + displacedY ) ;
} else if ( type = = Text : : Annotation ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( - 13 ) + displacedY ) ;
} else {
el - > setLayoutY ( staff . getLayoutYForHeight ( 22 ) + displacedY ) ;
}
} else if ( el - > event ( ) - > isa ( Indication : : EventType ) ) {
try {
std : : string indicationType =
el - > event ( ) - > get
< String > ( Indication : : IndicationTypePropertyName ) ;
if ( indicationType = = Indication : : Slur | |
indicationType = = Indication : : PhrasingSlur ) {
getSlurList ( staff ) . push_back ( i ) ;
}
if ( indicationType = = Indication : : OttavaUp | |
indicationType = = Indication : : QuindicesimaUp ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( 15 ) + displacedY ) ;
} else {
el - > setLayoutY ( staff . getLayoutYForHeight ( - 9 ) + displacedY ) ;
}
} catch ( . . . ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( - 9 ) + displacedY ) ;
}
} else if ( el - > event ( ) - > isa ( Guitar : : Chord : : EventType ) ) {
el - > setLayoutY ( staff . getLayoutYForHeight ( 22 ) + displacedY ) ;
}
}
}
PRINT_ELAPSED ( " NotationVLayout::scanStaff " ) ;
}
void
NotationVLayout : : finishLayout ( timeT , timeT )
{
START_TIMING ;
for ( SlurListMap : : iterator mi = m_slurs . begin ( ) ;
mi ! = m_slurs . end ( ) ; + + mi ) {
for ( SlurList : : iterator si = mi - > second . begin ( ) ;
si ! = mi - > second . end ( ) ; + + si ) {
NotationElementList : : iterator i = * si ;
NotationStaff & staff = dynamic_cast < NotationStaff & > ( * ( mi - > first ) ) ;
positionSlur ( staff , i ) ;
}
}
PRINT_ELAPSED ( " NotationVLayout::finishLayout " ) ;
}
void
NotationVLayout : : positionSlur ( NotationStaff & staff ,
NotationElementList : : iterator i )
{
NotationRules rules ;
bool phrasing = ( ( * i ) - > event ( ) - > get
< String > ( Indication : : IndicationTypePropertyName )
= = Indication : : PhrasingSlur ) ;
NotationElementList : : iterator scooter = i ;
timeT slurDuration = ( * i ) - > event ( ) - > getDuration ( ) ;
if ( slurDuration = = 0 & & ( * i ) - > event ( ) - > has ( " indicationduration " ) ) {
slurDuration = ( * i ) - > event ( ) - > get
< Int > ( " indicationduration " ) ; // obs property
}
timeT endTime = ( * i ) - > getViewAbsoluteTime ( ) + slurDuration ;
bool haveStart = false ;
int startTopHeight = 4 , endTopHeight = 4 ,
startBottomHeight = 4 , endBottomHeight = 4 ,
maxTopHeight = 4 , minBottomHeight = 4 ,
maxCount = 0 , minCount = 0 ;
int startX = ( int ) ( * i ) - > getLayoutX ( ) , endX = startX + 10 ;
bool startStemUp = false , endStemUp = false ;
long startMarks = 0 , endMarks = 0 ;
bool startTied = false , endTied = false ;
bool beamAbove = false , beamBelow = false ;
bool dynamic = false ;
std : : vector < Event * > stemUpNotes , stemDownNotes ;
// Scan the notes spanned by the slur, recording the top and
// bottom heights of the first and last chords, plus the presence
// of any troublesome beams and high or low notes in the body.
while ( scooter ! = staff . getViewElementList ( ) - > end ( ) ) {
if ( ( * scooter ) - > getViewAbsoluteTime ( ) > = endTime )
break ;
Event * event = ( * scooter ) - > event ( ) ;
if ( event - > isa ( Note : : EventType ) ) {
long h = 0 ;
if ( ! event - > get
< Int > ( m_properties . HEIGHT_ON_STAFF , h ) ) {
KMessageBox : : sorry
( ( TQWidget * ) parent ( ) , i18n ( " Spanned note at %1 has no HEIGHT_ON_STAFF property! \n This is a bug (the program would previously have crashed by now) " ) . arg ( ( * scooter ) - > getViewAbsoluteTime ( ) ) ) ;
event - > dump ( std : : cerr ) ;
}
bool stemUp = rules . isStemUp ( h ) ;
event - > get
< Bool > ( m_properties . VIEW_LOCAL_STEM_UP , stemUp ) ;
bool beamed = false ;
event - > get
< Bool > ( m_properties . BEAMED , beamed ) ;
bool primary = false ;
if ( event - > get
< Bool >
( m_properties . CHORD_PRIMARY_NOTE , primary ) & & primary ) {
NotationChord chord ( * ( staff . getViewElementList ( ) ) , scooter ,
m_notationQuantizer , m_properties ) ;
if ( beamed ) {
if ( stemUp )
beamAbove = true ;
else
beamBelow = true ;
}
if ( ! haveStart ) {
startBottomHeight = chord . getLowestNoteHeight ( ) ;
startTopHeight = chord . getHighestNoteHeight ( ) ;
minBottomHeight = startBottomHeight ;
maxTopHeight = startTopHeight ;
startX = ( int ) ( * scooter ) - > getLayoutX ( ) ;
startStemUp = stemUp ;
startMarks = chord . getMarkCountForChord ( ) ;
bool tied = false ;
if ( ( event - > get
< Bool > ( TIED_FORWARD , tied ) & & tied ) | |
( event - > get < Bool > ( TIED_BACKWARD , tied ) & & tied ) ) {
startTied = true ;
}
haveStart = true ;
} else {
if ( chord . getLowestNoteHeight ( ) < minBottomHeight ) {
minBottomHeight = chord . getLowestNoteHeight ( ) ;
+ + minCount ;
}
if ( chord . getHighestNoteHeight ( ) > maxTopHeight ) {
maxTopHeight = chord . getHighestNoteHeight ( ) ;
+ + maxCount ;
}
}
endBottomHeight = chord . getLowestNoteHeight ( ) ;
endTopHeight = chord . getHighestNoteHeight ( ) ;
endX = ( int ) ( * scooter ) - > getLayoutX ( ) ;
endStemUp = stemUp ;
endMarks = chord . getMarkCountForChord ( ) ;
bool tied = false ;
if ( ( event - > get
< Bool > ( TIED_FORWARD , tied ) & & tied ) | |
( event - > get < Bool > ( TIED_BACKWARD , tied ) & & tied ) ) {
endTied = true ;
}
}
if ( ! beamed ) {
if ( stemUp )
stemUpNotes . push_back ( event ) ;
else
stemDownNotes . push_back ( event ) ;
}
} else if ( event - > isa ( Indication : : EventType ) ) {
try {
std : : string indicationType =
event - > get
< String > ( Indication : : IndicationTypePropertyName ) ;
if ( indicationType = = Indication : : Crescendo | |
indicationType = = Indication : : Decrescendo )
dynamic = true ;
} catch ( . . . ) { }
}
+ + scooter ;
}
bool above = true ;
if ( ( * i ) - > event ( ) - > has ( NotationProperties : : SLUR_ABOVE ) & &
( * i ) - > event ( ) - > isPersistent < Bool > ( NotationProperties : : SLUR_ABOVE ) ) {
( * i ) - > event ( ) - > get
< Bool > ( NotationProperties : : SLUR_ABOVE , above ) ;
} else if ( phrasing ) {
int score = 0 ; // for "above"
if ( dynamic )
score + = 2 ;
if ( startStemUp = = endStemUp ) {
if ( startStemUp )
score - = 2 ;
else
score + = 2 ;
} else if ( beamBelow ! = beamAbove ) {
if ( beamAbove )
score - = 2 ;
else
score + = 2 ;
}
if ( maxTopHeight < 6 )
score + = 1 ;
else if ( minBottomHeight > 2 )
score - = 1 ;
if ( stemUpNotes . size ( ) ! = stemDownNotes . size ( ) ) {
if ( stemUpNotes . size ( ) < stemDownNotes . size ( ) )
score + = 1 ;
else
score - = 1 ;
}
above = ( score > = 0 ) ;
} else {
if ( startStemUp = = endStemUp ) {
above = ! startStemUp ;
} else if ( beamBelow ) {
above = true ;
} else if ( beamAbove ) {
above = false ;
} else if ( stemUpNotes . size ( ) ! = stemDownNotes . size ( ) ) {
above = ( stemUpNotes . size ( ) < stemDownNotes . size ( ) ) ;
} else {
above = ( ( startTopHeight - 4 ) + ( endTopHeight - 4 ) +
( 4 - startBottomHeight ) + ( 4 - endBottomHeight ) < = 8 ) ;
}
}
// now choose the actual y-coord of the slur based on the side
// we've decided to put it on
int startHeight , endHeight ;
int startOffset = 2 , endOffset = 2 ;
if ( above ) {
if ( ! startStemUp )
startOffset + = startMarks * 2 ;
else
startOffset + = 5 ;
if ( ! endStemUp )
endOffset + = startMarks * 2 ;
else
endOffset + = 5 ;
startHeight = startTopHeight + startOffset ;
endHeight = endTopHeight + endOffset ;
bool maxRelevant = ( ( maxTopHeight ! = endTopHeight ) | | ( maxCount > 1 ) ) ;
if ( maxRelevant ) {
int midHeight = ( startHeight + endHeight ) / 2 ;
if ( maxTopHeight > midHeight - 1 ) {
startHeight + = maxTopHeight - midHeight + 1 ;
endHeight + = maxTopHeight - midHeight + 1 ;
}
}
} else {
if ( startStemUp )
startOffset + = startMarks * 2 ;
else
startOffset + = 5 ;
if ( endStemUp )
endOffset + = startMarks * 2 ;
else
endOffset + = 5 ;
startHeight = startBottomHeight - startOffset ;
endHeight = endBottomHeight - endOffset ;
bool minRelevant = ( ( minBottomHeight ! = endBottomHeight ) | | ( minCount > 1 ) ) ;
if ( minRelevant ) {
int midHeight = ( startHeight + endHeight ) / 2 ;
if ( minBottomHeight < midHeight + 1 ) {
startHeight - = midHeight - minBottomHeight + 1 ;
endHeight - = midHeight - minBottomHeight + 1 ;
}
}
}
int y0 = staff . getLayoutYForHeight ( startHeight ) ,
y1 = staff . getLayoutYForHeight ( endHeight ) ;
int dy = y1 - y0 ;
int length = endX - startX ;
int diff = staff . getLayoutYForHeight ( 0 ) - staff . getLayoutYForHeight ( 3 ) ;
if ( length < diff * 10 )
diff / = 2 ;
if ( length > diff * 3 )
length - = diff / 2 ;
startX + = diff ;
( * i ) - > event ( ) - > setMaybe < Bool > ( NotationProperties : : SLUR_ABOVE , above ) ;
( * i ) - > event ( ) - > setMaybe < Int > ( m_properties . SLUR_Y_DELTA , dy ) ;
( * i ) - > event ( ) - > setMaybe < Int > ( m_properties . SLUR_LENGTH , length ) ;
double displacedX = 0.0 , displacedY = 0.0 ;
long dxRaw = 0 ;
( * i ) - > event ( ) - > get < Int > ( DISPLACED_X , dxRaw ) ;
displacedX = double ( dxRaw * m_npf - > getNoteBodyWidth ( ) ) / 1000.0 ;
long dyRaw = 0 ;
( * i ) - > event ( ) - > get < Int > ( DISPLACED_Y , dyRaw ) ;
displacedY = double ( dyRaw * m_npf - > getLineSpacing ( ) ) / 1000.0 ;
( * i ) - > setLayoutX ( startX + displacedX ) ;
( * i ) - > setLayoutY ( y0 + displacedY ) ;
}
}