data_STEMDIRECTION LayerElement::GetDrawingStemDir() { if (this->Is() == NOTE) { Note *note = dynamic_cast<Note*>(this); assert( note ); return note->GetDrawingStemDir(); } if (this->Is() == CHORD) { Chord *chord = dynamic_cast<Chord*>(this); assert( chord ); return chord->GetDrawingStemDir(); } return STEMDIRECTION_NONE; }
data_STEMDIRECTION View::GetTupletCoordinates(Tuplet *tuplet, Layer *layer, Point *start, Point *end, Point *center) { assert(tuplet); assert(layer); assert(start); assert(end); assert(center); Point first, last; int x, y; data_STEMDIRECTION direction = STEMDIRECTION_up; ListOfObjects *tupletChildren = tuplet->GetList(tuplet); LayerElement *firstElement = dynamic_cast<LayerElement *>(tupletChildren->front()); LayerElement *lastElement = dynamic_cast<LayerElement *>(tupletChildren->back()); // AllNotesBeamed tries to figure out if all the notes are in the same beam if (OneBeamInTuplet(tuplet)) { // yes they are in a beam x = firstElement->GetDrawingX() + (lastElement->GetDrawingX() - firstElement->GetDrawingX() + lastElement->m_selfBB_x2) / 2; // align the center point at the exact center of the first an last stem // TUPLET_OFFSET is summed so it does not collide with the stem Note *firstNote = dynamic_cast<Note *>(tuplet->FindChildByType(NOTE)); Note *lastNote = dynamic_cast<Note *>(tuplet->FindChildByType(NOTE, UNLIMITED_DEPTH, BACKWARD)); y = firstElement->GetDrawingY(); if (firstNote && lastNote) { if (firstNote->GetDrawingStemDir() == STEMDIRECTION_up) y = lastNote->GetDrawingStemEnd().y + (firstNote->GetDrawingStemEnd().y - lastNote->GetDrawingStemEnd().y) / 2 + TUPLET_OFFSET; else y = lastNote->GetDrawingStemEnd().y + (firstNote->GetDrawingStemEnd().y - lastNote->GetDrawingStemEnd().y) / 2 - TUPLET_OFFSET; } // Copy the generated coordinates center->x = x; center->y = y; direction = firstNote->GetDrawingStemDir(); // stem direction is the same for all notes } else { // There are unbeamed notes of two different beams // treat all the notes as unbeamed int ups = 0, downs = 0; // quantity of up- and down-stems // In this case use the center of the notehead to calculate the exact center // as it looks better x = firstElement->GetDrawingX() + (lastElement->GetDrawingX() - firstElement->GetDrawingX() + lastElement->m_selfBB_x2) / 2; // Return the start and end position for the brackes // starting from the first edge and last of the BBoxes start->x = firstElement->m_selfBB_x1 + firstElement->GetDrawingX(); end->x = lastElement->m_selfBB_x2 + lastElement->GetDrawingX(); // The first step is to calculate all the stem directions // cycle into the elements and count the up and down dirs ListOfObjects::iterator iter = tupletChildren->begin(); while (iter != tupletChildren->end()) { if ((*iter)->Is() == NOTE) { Note *currentNote = dynamic_cast<Note *>(*iter); assert(currentNote); if (currentNote->GetDrawingStemDir() == STEMDIRECTION_up) ups++; else downs++; } ++iter; } // true means up direction = ups > downs ? STEMDIRECTION_up : STEMDIRECTION_down; // if ups or downs are 0, it means all the stems go in the same direction if (ups == 0 || downs == 0) { Note *firstNote = dynamic_cast<Note *>(tuplet->FindChildByType(NOTE)); Note *lastNote = dynamic_cast<Note *>(tuplet->FindChildByType(NOTE, UNLIMITED_DEPTH, BACKWARD)); // Calculate the average between the first and last stem // set center, start and end too. y = firstElement->GetDrawingY(); if (firstNote && lastNote) { if (direction == STEMDIRECTION_up) { // up y = lastNote->GetDrawingStemEnd().y + (firstNote->GetDrawingStemEnd().y - lastNote->GetDrawingStemEnd().y) / 2 + TUPLET_OFFSET; start->y = firstNote->GetDrawingStemEnd().y + TUPLET_OFFSET; end->y = lastNote->GetDrawingStemEnd().y + TUPLET_OFFSET; } else { y = lastNote->GetDrawingStemEnd().y + (firstNote->GetDrawingStemEnd().y - lastNote->GetDrawingStemEnd().y) / 2 - TUPLET_OFFSET; start->y = firstNote->GetDrawingStemEnd().y - TUPLET_OFFSET; end->y = lastNote->GetDrawingStemEnd().y - TUPLET_OFFSET; } } // Now we cycle again in all the intermediate notes (i.e. we start from the second note // and stop at last -1) // We will see if the position of the note is more (or less for down stems) of the calculated // average. In this case we offset down or up all the points iter = tupletChildren->begin(); while (iter != tupletChildren->end()) { if ((*iter)->Is() == NOTE) { Note *currentNote = dynamic_cast<Note *>(*iter); assert(currentNote); if (direction == STEMDIRECTION_up) { // The note is more than the avg, adjust to y the difference // from this note to the avg if (currentNote->GetDrawingStemEnd().y + TUPLET_OFFSET > y) { int offset = y - (currentNote->GetDrawingStemEnd().y + TUPLET_OFFSET); y -= offset; end->y -= offset; start->y -= offset; } } else { if (currentNote->GetDrawingStemEnd().y - TUPLET_OFFSET < y) { int offset = y - (currentNote->GetDrawingStemEnd().y - TUPLET_OFFSET); y -= offset; end->y -= offset; start->y -= offset; } } } ++iter; } } else { // two-directional beams // this case is similar to the above, but the bracket is only horizontal // y is 0 because the final y pos is above the tallest stem y = 0; // Find the tallest stem and set y to it (with the offset distance) iter = tupletChildren->begin(); while (iter != tupletChildren->end()) { if ((*iter)->Is() == NOTE) { Note *currentNote = dynamic_cast<Note *>(*iter); assert(currentNote); if (currentNote->GetDrawingStemDir() == direction) { if (direction == STEMDIRECTION_up) { if (y == 0 || currentNote->GetDrawingStemEnd().y + TUPLET_OFFSET >= y) y = currentNote->GetDrawingStemEnd().y + TUPLET_OFFSET; } else { if (y == 0 || currentNote->GetDrawingStemEnd().y - TUPLET_OFFSET <= y) y = currentNote->GetDrawingStemEnd().y - TUPLET_OFFSET; } } else { // do none for now // but if a notehead with a reversed stem is taller that the last // calculated y, we need to offset } } ++iter; } // end and start are on the same line (and so il center when set later) end->y = start->y = y; } } center->x = x; center->y = y; return direction; }
void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff) { assert(dc); assert(element); assert(layer); assert(staff); LogDebug("DrawLigatureNote"); Note *note = dynamic_cast<Note *>(element); assert(note); int xn, x1, x2, y, y1, y2, y3, y4; // int yy2, y5; // unused int verticalCenter, up, epaisseur; epaisseur = std::max(2, m_doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, false) / 2); xn = element->GetDrawingX(); y = 99; // LogDebug("DrawLigatureNote: _ligObliqua=%d drawingX=%d y=%d", note->m_ligObliqua, xn, y); LogDebug("DrawLigatureNote: drawingX=%d y=%d", xn, y); /* if ((note->m_lig==LIG_MEDIAL) || (note->m_lig==LIG_TERMINAL)) { CalculateLigaturePosX(element, layer, staff); } else */ { xn = element->GetDrawingX(); } // Compute the dimensions of the rectangle x1 = xn - m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); x2 = xn + m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); y1 = y + m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 = y - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y3 = (int)(y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / 2); // part of the frame that overflows y4 = (int)(y2 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / 2); // if (!note->m_ligObliqua && (!View::s_drawingLigObliqua)) // rectangular notes, incl. ligature { if (note->GetColored() != BOOLEAN_true) { // double the bases of rectangles DrawObliquePolygon(dc, x1, y1, x2, y1, -epaisseur); DrawObliquePolygon(dc, x1, y2, x2, y2, epaisseur); } else DrawFilledRectangle(dc, x1, y1, x2, y2); // // ENZ correction of x2 DrawVerticalLine(dc, y3, y4, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); // lateral brace DrawVerticalLine(dc, y3, y4, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } /* else // handle obliques { if (!View::s_drawingLigObliqua) // 1st pass: Initial flagStemHeight { DrawVerticalLine (dc,y3,y4,x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); View::s_drawingLigObliqua = true; //oblique = false; // if (val == DUR_1) // left tail up if DUR_1 // queue_lig = true; } else // 2nd pass: oblique lines and final flagStemHeighte { x1 -= m_doc->m_drawingBrevisWidth[staff->m_drawingStaffSize] * 2; // auto advance y1 = *View::s_drawingLigY - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); // ligat_y contains original y yy2 = y2; y5 = y1+ m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); y2 += m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); // go up a INTERL if (note->GetColored()==BOOLEAN_true) DrawObliquePolygon (dc, x1, y1, x2, yy2, m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)); else { DrawObliquePolygon (dc, x1, y1, x2, yy2, 5); DrawObliquePolygon (dc, x1, y5, x2, y2, -5); } DrawVerticalLine (dc,y3,y4,x2,m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); // enclosure flagStemHeighte View::s_drawingLigObliqua = false; // queue_lig = false; // ??defuses alg.queue DUR_BR?? } } if (note->m_lig) // remember positions from one note to another; connect notes by bars { *(View::s_drawingLigX+1) = x2; *(View::s_drawingLigY+1) = y; // connect ligature beamed notes by bar flagStemHeightes //if (in(x1,(*View::s_drawingLigX)-2,(*View::s_drawingLigX)+2) || (this->fligat && this->lat && !Note1::marq_obl)) // the latest conditions to allow previous ligature flagStemHeighte // DrawVerticalLine (dc, *ligat_y, y1, (this->fligat && this->lat) ? x2: x1, m_doc->m_parameters.m_stemWidth); // ax2 - drawing flagStemHeight lines missing *View::s_drawingLigX = *(View::s_drawingLigX + 1); *View::s_drawingLigY = *(View::s_drawingLigY + 1); } y3 = y2 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; if (note->m_lig) { if (note->m_dur == DUR_BR) // && this->queue_lig) // tail left bottom: initial downward DUR_BR // ax2 - no support for queue_lig (see WG corrigeLigature) { DrawVerticalLine (dc, y2, y3, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } else if (note->m_dur == DUR_LG) // && !this->queue_lig) // DUR_LG ligature, tail right down // ax2 - no support for queue_lig { DrawVerticalLine (dc, y2, y3, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } else if (note->m_dur == DUR_1) // && this->queue_lig) // queue gauche haut // ax2 - no support for queue_lig { y2 = y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; DrawVerticalLine (dc, y1, y2, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } } else if (note->m_dur == DUR_LG) // isolated DUR_LG: tail like normal notes */ if (note->GetActualDur() == DUR_LG) { verticalCenter = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) * 2; // ENZ up = (y < verticalCenter) ? true : false; // ENZ if (note->GetDrawingStemDir() != STEMDIRECTION_NONE) { if (note->GetDrawingStemDir() == STEMDIRECTION_up) { up = true; } else { up = false; } } if (!up) { y3 = y1 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 8; y2 = y1; } else { y3 = y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 6; y2 = y1; } DrawVerticalLine(dc, y2, y3, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } return; }
int Artic::CalcArtic(FunctorParams *functorParams) { FunctorDocParams *params = dynamic_cast<FunctorDocParams *>(functorParams); assert(params); /************** Get the parent and the stem direction **************/ LayerElement *parent = NULL; Note *parentNote = NULL; Chord *parentChord = dynamic_cast<Chord *>(this->GetFirstParent(CHORD, 2)); data_STEMDIRECTION stemDir = STEMDIRECTION_NONE; data_STAFFREL place = STAFFREL_NONE; if (!parentChord) { parentNote = dynamic_cast<Note *>(this->GetFirstParent(NOTE)); parent = parentNote; } else { parent = parentChord; } if (!parentChord && !parentNote) { // no parent chord or note, nothing we can do... return FUNCTOR_CONTINUE; } Staff *staff = dynamic_cast<Staff *>(this->GetFirstParent(STAFF)); assert(staff); Layer *layer = dynamic_cast<Layer *>(this->GetFirstParent(LAYER)); assert(layer); stemDir = parentNote ? parentNote->GetDrawingStemDir() : parentChord->GetDrawingStemDir(); /************** placement **************/ bool allowAbove = true; // for now we ignore within @place if (this->HasPlace() && (this->GetPlace() != STAFFREL_within)) { place = this->GetPlace(); // If we have a place indication do not allow to be changed to above allowAbove = false; } else if (layer->GetDrawingStemDir() != STEMDIRECTION_NONE) { place = (layer->GetDrawingStemDir() == STEMDIRECTION_up) ? STAFFREL_above : STAFFREL_below; // If we have more than one layer do not allow to be changed to above allowAbove = false; } else if (stemDir == STEMDIRECTION_up) place = STAFFREL_below; else place = STAFFREL_above; /************** set it to both the inside and outside part **************/ ArticPart *insidePart = this->GetInsidePart(); ArticPart *outsidePart = this->GetOutsidePart(); if (insidePart) { insidePart->SetPlace(place); } if (outsidePart) { // If allowAbove is true it will place the above if the content requires so (even if place below if given) if (place == STAFFREL_below && allowAbove && outsidePart->AlwaysAbove()) place = STAFFREL_above; outsidePart->SetPlace(place); } /************** calculate the y position **************/ Staff *staffAbove = NULL; Staff *staffBelow = NULL; // Cross-staff handling of articulation will need to be re-thought. We can look at assiging a cross-staff to the // appropriate ArticPart // (see below) - For chords, we need to distinguish cross-staff chords and cross-staff chord notes if (parent->m_crossStaff && parent->m_crossLayer) { staff = parent->m_crossStaff; staffAbove = staff; staffBelow = staff; } else if (parentChord) { parentChord->GetCrossStaffExtremes(staffAbove, staffBelow); } int staffYBottom = -params->m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize); // Avoid in artic to be in legder lines int yInAbove = std::max( parent->GetDrawingTop(params->m_doc, staff->m_drawingStaffSize, false) - staff->GetDrawingY(), staffYBottom); int yInBelow = std::min(parent->GetDrawingBottom(params->m_doc, staff->m_drawingStaffSize, false) - staff->GetDrawingY(), 0); int yOutAbove = std::max(yInAbove, 0); int yOutBelow = std::min(yInBelow, staffYBottom); // Does not work properly with chords, needs rethinking - It might be better to make artic or articPart relative to // notes // The problem is that in MEI artic are children of chord element and not of the notes if (insidePart) { if (insidePart->GetPlace() == STAFFREL_above) { insidePart->SetDrawingYRel(yInAbove); insidePart->m_crossStaff = staffAbove; } else { insidePart->SetDrawingYRel(yInBelow); insidePart->m_crossStaff = staffBelow; } } if (outsidePart) { if (outsidePart->GetPlace() == STAFFREL_above) { outsidePart->SetDrawingYRel(yOutAbove); outsidePart->m_crossStaff = staffAbove; } else { outsidePart->SetDrawingYRel(yOutBelow); outsidePart->m_crossStaff = staffBelow; } } // If we have both an inside and outside part we need to move the outside part away when they are both on the same // side if (insidePart && outsidePart) { int margin = params->m_doc->GetTopMargin(insidePart->GetClassId()) * params->m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / PARAM_DENOMINATOR; if (insidePart->GetPlace() == outsidePart->GetPlace()) { if (insidePart->GetPlace() == STAFFREL_above) { int inTop = insidePart->GetContentTop(); int outBottom = outsidePart->GetContentBottom(); if (inTop > outBottom) outsidePart->SetDrawingYRel(outsidePart->GetDrawingYRel() + inTop - outBottom + margin); } else { int inBottom = insidePart->GetContentBottom(); int outTop = outsidePart->GetContentTop(); if (inBottom < outTop) outsidePart->SetDrawingYRel(outsidePart->GetDrawingYRel() + outTop - inBottom + margin); } } } return FUNCTOR_SIBLINGS; }
void View::DrawMaximaToBrevis(DeviceContext *dc, int y, LayerElement *element, Layer *layer, Staff *staff) { assert(dc); assert(element); assert(layer); assert(staff); Note *note = dynamic_cast<Note *>(element); assert(note); int xn, xLeft, xRight, yTop, yBottom, y3, y4; // int yy2, y5; // unused int verticalCenter, up, height; bool mensural_black = (staff->m_drawingNotationType == NOTATIONTYPE_mensural_black); bool fillNotehead = (mensural_black || note->GetColored()) && !(mensural_black && note->GetColored()); height = m_doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, false) / 2; xn = element->GetDrawingX(); // Calculate size of the rectangle xLeft = xn - m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); xRight = xn + m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); if (note->GetActualDur() == DUR_MX) { // Maxima is twice the width of brevis xLeft -= m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); xRight += m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); } yTop = y + m_doc->GetDrawingUnit(staff->m_drawingStaffSize); yBottom = y - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y3 = yTop; y4 = yBottom; if (!mensural_black) { y3 += (int)m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / 2; // partie d'encadrement qui depasse y4 -= (int)m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / 2; } if (!fillNotehead) { // double the bases of rectangles DrawObliquePolygon(dc, xLeft, yTop, xRight, yTop, -height); DrawObliquePolygon(dc, xLeft, yBottom, xRight, yBottom, height); } else { DrawFilledRectangle(dc, xLeft, yTop, xRight, yBottom); } DrawVerticalLine(dc, y3, y4, xLeft, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); // corset lateral DrawVerticalLine(dc, y3, y4, xRight, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); // stem if (note->GetActualDur() < DUR_BR) { verticalCenter = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) * 2; up = (y < verticalCenter) ? true : false; if (note->GetDrawingStemDir() != STEMDIRECTION_NONE) { if (note->GetDrawingStemDir() == STEMDIRECTION_up) { up = true; } else { up = false; } } if (!up) { y3 = yTop - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 8; yBottom = yTop; } else { y3 = yTop + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 6; yBottom = yTop; } DrawVerticalLine(dc, yBottom, y3, xRight, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); } return; }
void View::DrawSlurInitial(FloatingCurvePositioner *curve, Slur *slur, int x1, int x2, Staff *staff, char spanningType) { Beam *parentBeam = NULL; Chord *startParentChord = NULL; Chord *endParentChord = NULL; Note *startNote = NULL; Note *endNote = NULL; Chord *startChord = NULL; Chord *endChord = NULL; curvature_CURVEDIR drawingCurveDir = curvature_CURVEDIR_above; data_STEMDIRECTION startStemDir = STEMDIRECTION_NONE; data_STEMDIRECTION endStemDir = STEMDIRECTION_NONE; data_STEMDIRECTION stemDir = STEMDIRECTION_NONE; bool isGraceToNoteSlur = false; int y1 = staff->GetDrawingY(); int y2 = staff->GetDrawingY(); /************** parent layers **************/ LayerElement *start = dynamic_cast<LayerElement *>(slur->GetStart()); LayerElement *end = dynamic_cast<LayerElement *>(slur->GetEnd()); if (!start || !end) { // no start and end, obviously nothing to do... return; } if (start->Is(TIMESTAMP_ATTR) && end->Is(TIMESTAMP_ATTR)) { // for now ignore slur using 2 tstamps return; } if (start->Is(NOTE)) { startNote = dynamic_cast<Note *>(start); assert(startNote); startParentChord = startNote->IsChordTone(); startStemDir = startNote->GetDrawingStemDir(); } else if (start->Is(CHORD)) { startChord = dynamic_cast<Chord *>(start); assert(startChord); startStemDir = startChord->GetDrawingStemDir(); } if (end->Is(NOTE)) { endNote = dynamic_cast<Note *>(end); assert(endNote); endParentChord = endNote->IsChordTone(); endStemDir = endNote->GetDrawingStemDir(); } else if (end->Is(CHORD)) { endChord = dynamic_cast<Chord *>(end); assert(endChord); endStemDir = endChord->GetDrawingStemDir(); } if (startNote && endNote && startNote->IsGraceNote() && !endNote->IsGraceNote()) { isGraceToNoteSlur = true; } Layer *layer = NULL; LayerElement *layerElement = NULL; // For now, with timestamps, get the first layer. We should eventually look at the @layerident (not implemented) if (!start->Is(TIMESTAMP_ATTR)) { layer = dynamic_cast<Layer *>(start->GetFirstParent(LAYER)); layerElement = start; } else { layer = dynamic_cast<Layer *>(end->GetFirstParent(LAYER)); layerElement = end; } assert(layer); if (!start->Is(TIMESTAMP_ATTR) && !end->Is(TIMESTAMP_ATTR) && (spanningType == SPANNING_START_END)) { System *system = dynamic_cast<System *>(staff->GetFirstParent(SYSTEM)); assert(system); // If we have a start to end situation, then store the curvedir in the slur for mixed drawing stem dir // situations if (system->HasMixedDrawingStemDir(start, end)) { slur->SetDrawingCurvedir(curvature_CURVEDIR_above); } } /************** calculate the radius for adjusting the x position **************/ int startRadius = 0; if (!start->Is(TIMESTAMP_ATTR)) { startRadius = start->GetDrawingRadius(m_doc); } int endRadius = 0; if (!end->Is(TIMESTAMP_ATTR)) { endRadius = end->GetDrawingRadius(m_doc); } /************** note stem dir **************/ if (spanningType == SPANNING_START_END) { stemDir = startStemDir; } // This is the case when the tie is split over two system of two pages. // In this case, we are now drawing its beginning to the end of the measure (i.e., the last aligner) else if (spanningType == SPANNING_START) { stemDir = startStemDir; } // Now this is the case when the tie is split but we are drawing the end of it else if (spanningType == SPANNING_END) { stemDir = endStemDir; } // Finally, slur accross an entire system; use the staff position and up (see below) else { stemDir = STEMDIRECTION_down; } /************** direction **************/ data_STEMDIRECTION layerStemDir; // first should be the tie @curvedir if (slur->HasCurvedir()) { drawingCurveDir = (slur->GetCurvedir() == curvature_CURVEDIR_above) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } // grace notes - always below unless we have a drawing stem direction on the layer else if (isGraceToNoteSlur && (layer->GetDrawingStemDir(layerElement) == STEMDIRECTION_NONE)) { drawingCurveDir = curvature_CURVEDIR_below; } // the normal case else if (slur->HasDrawingCurvedir()) { drawingCurveDir = slur->GetDrawingCurvedir(); } // then layer direction trumps note direction else if (layer && ((layerStemDir = layer->GetDrawingStemDir(layerElement)) != STEMDIRECTION_NONE)) { drawingCurveDir = (layerStemDir == STEMDIRECTION_up) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } // look if in a chord else if (startParentChord) { if (startParentChord->PositionInChord(startNote) < 0) { drawingCurveDir = curvature_CURVEDIR_below; } else if (startParentChord->PositionInChord(startNote) > 0) { drawingCurveDir = curvature_CURVEDIR_above; } // away from the stem if odd number (center note) else { drawingCurveDir = (stemDir != STEMDIRECTION_up) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } } else if (stemDir == STEMDIRECTION_up) { drawingCurveDir = curvature_CURVEDIR_below; } else if (stemDir == STEMDIRECTION_NONE) { // no information from the note stem directions, look at the position in the notes int center = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) * 2; drawingCurveDir = (start->GetDrawingY() > center) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } /************** adjusting y position **************/ bool isShortSlur = false; if (x2 - x1 < 1 * m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)) isShortSlur = true; int yChordMax, yChordMin; if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_START)) { // first get the min max of the chord (if any) if (startParentChord) { startParentChord->GetYExtremes(yChordMax, yChordMin); } else if (startChord) { startChord->GetYExtremes(yChordMax, yChordMin); } // slur is up if (drawingCurveDir == curvature_CURVEDIR_above) { // P(^) if (startStemDir == STEMDIRECTION_down) y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); // d(^)d else if (isShortSlur) { y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); } // same but in beam - adjust the x too else if ((parentBeam = start->IsInBeam()) && !parentBeam->IsLastInBeam(start)) { y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); x1 += startRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // d(^) else { // put it on the side, move it left, but not if we have a @stamp if (!start->Is(TIMESTAMP_ATTR)) x1 += m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 4 / 2; if (startChord || startParentChord) y1 = yChordMin + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y1 = start->GetDrawingY() + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } // slur is down else { // d(_) if (startStemDir == STEMDIRECTION_up) y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // P(_)P else if (isShortSlur) { y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); } // same but in beam else if ((parentBeam = start->IsInBeam()) && !parentBeam->IsLastInBeam(start)) { y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); x1 -= startRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // P(_) else { // put it on the side, but no need to move it left if (startChord || startParentChord) y1 = yChordMin - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y1 = start->GetDrawingY() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } } if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_END)) { // get the min max of the chord if any if (endParentChord) { endParentChord->GetYExtremes(yChordMax, yChordMin); } else if (endChord) { endChord->GetYExtremes(yChordMax, yChordMin); } // get the stem direction of the end // slur is up if (drawingCurveDir == curvature_CURVEDIR_above) { // (^)P if (endStemDir == STEMDIRECTION_down) y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); // d(^)d else if (isShortSlur) { y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); } // same but in beam - adjust the x too else if ((parentBeam = end->IsInBeam()) && !parentBeam->IsFirstInBeam(end)) { y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); x2 += endRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // (^)d else { // put it on the side, no need to move it right if (endChord || endParentChord) y2 = yChordMin + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y2 = end->GetDrawingY() + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } else { if (isGraceToNoteSlur) { if (endNote) { y2 = endNote->GetDrawingY(); x2 -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 2; isShortSlur = true; } else { y2 = y1; } } // (_)d else if (endStemDir == STEMDIRECTION_up) y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // P(_)P else if (isShortSlur) { y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); } // same but in beam else if ((parentBeam = end->IsInBeam()) && !parentBeam->IsFirstInBeam(end)) { y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // x2 -= endRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // (_)P else { // put it on the side, move it right, but not if we have a @stamp2 if (!end->Is(TIMESTAMP_ATTR)) x2 -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 2; if (endChord || endParentChord) y2 = yChordMin - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y2 = end->GetDrawingY() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } } // Positions not attached to a note if (spanningType == SPANNING_START) { if (drawingCurveDir == curvature_CURVEDIR_above) y2 = std::max(staff->GetDrawingY(), y1); else y2 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y1); } if (end->Is(TIMESTAMP_ATTR)) { if (drawingCurveDir == curvature_CURVEDIR_above) y2 = std::max(staff->GetDrawingY(), y1); else y2 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y1); } if (spanningType == SPANNING_END) { if (drawingCurveDir == curvature_CURVEDIR_above) y1 = std::max(staff->GetDrawingY(), y2); else y1 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y2); } if (start->Is(TIMESTAMP_ATTR)) { if (drawingCurveDir == curvature_CURVEDIR_above) y1 = std::max(staff->GetDrawingY(), y2); else y1 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y2); } // slur accross an entire system; use the staff position else if (spanningType == SPANNING_MIDDLE) { // To be adjusted if (drawingCurveDir == curvature_CURVEDIR_above) y1 = staff->GetDrawingY(); else y1 = staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize); y2 = y1; } /************** y position **************/ if (drawingCurveDir == curvature_CURVEDIR_above) { y1 += 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 += 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); } else { y1 -= 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 -= 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); } Point points[4]; points[0] = Point(x1, y1); points[3] = Point(x2, y2); float angle = CalcInitialSlur(curve, slur, staff, layer->GetN(), drawingCurveDir, points); int thickness = m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * m_options->m_slurThickness.GetValue(); curve->UpdateCurveParams(points, angle, thickness, drawingCurveDir); /************** articulation **************/ // First get all artic children ClassIdComparison matchType(ARTIC); ArrayOfObjects artics; ArrayOfObjects::iterator articIter; // the normal case or start if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_START)) { start->FindAllChildByComparison(&artics, &matchType); // Then the @n of each first staffDef for (articIter = artics.begin(); articIter != artics.end(); ++articIter) { Artic *artic = dynamic_cast<Artic *>(*articIter); assert(artic); ArticPart *outsidePart = artic->GetOutsidePart(); if (outsidePart) { if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_above) && (drawingCurveDir == curvature_CURVEDIR_above)) { outsidePart->AddSlurPositioner(curve, true); } else if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_below) && (drawingCurveDir == curvature_CURVEDIR_below)) { outsidePart->AddSlurPositioner(curve, true); } } } } // normal case or end if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_END)) { end->FindAllChildByComparison(&artics, &matchType); // Then the @n of each first staffDef for (articIter = artics.begin(); articIter != artics.end(); ++articIter) { Artic *artic = dynamic_cast<Artic *>(*articIter); assert(artic); ArticPart *outsidePart = artic->GetOutsidePart(); if (outsidePart) { if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_above) && (drawingCurveDir == curvature_CURVEDIR_above)) { outsidePart->AddSlurPositioner(curve, false); } else if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_below) && (drawingCurveDir == curvature_CURVEDIR_below)) { outsidePart->AddSlurPositioner(curve, false); } } } } return; }
void View::DrawLigature ( DeviceContext *dc, int y, LayerElement *element, Layer *layer, Staff *staff ) { assert( dc ); assert( element ); assert( layer ); assert( staff ); Note *note = dynamic_cast<Note*>(element); assert( note ); int xn, x1, x2, y1, y2, y3, y4; // int yy2, y5; // unused int verticalCenter, up, epaisseur; epaisseur = std::max (2, m_doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, false) / 2); xn = element->GetDrawingX(); /* if ((note->m_lig==LIG_MEDIAL) || (note->m_lig==LIG_TERMINAL)) { CalculateLigaturePosX ( element, layer, staff ); } else */{ xn = element->GetDrawingX(); } // calcul des dimensions du rectangle x1 = xn - m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); x2 = xn + m_doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize); y1 = y + m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 = y - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y3 = (int)(y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)/2); // partie d'encadrement qui depasse y4 = (int)(y2 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)/2); //if (!note->m_ligObliqua && (!View::s_drawingLigObliqua)) // notes rectangulaires, y c. en ligature { if (note->GetColored()!=BOOLEAN_true) { // double base des carrees DrawObliquePolygon ( dc, x1, y1, x2, y1, -epaisseur ); DrawObliquePolygon ( dc, x1, y2, x2, y2, epaisseur ); } else DrawFullRectangle( dc,x1,y1,x2,y2); // dessine val carree pleine // ENZ correction de x2 DrawVerticalLine ( dc, y3, y4, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); // corset lateral DrawVerticalLine ( dc, y3, y4, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } /* else // traitement des obliques { if (!View::s_drawingLigObliqua) // 1e passage: ligne flagStemHeighte initiale { DrawVerticalLine (dc,y3,y4,x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); View::s_drawingLigObliqua = true; //oblique = OFF; // if (val == DUR_1) // queue gauche haut si DUR_1 // queue_lig = ON; } else // 2e passage: lignes obl. et flagStemHeighte finale { x1 -= m_doc->m_drawingBrevisWidth[staff->m_drawingStaffSize]*2; // avance auto y1 = *View::s_drawingLigY - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); // ligat_y contient y original yy2 = y2; y5 = y1+ m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); y2 += m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); // on monte d'un INTERL if (note->GetColored()==BOOLEAN_true) DrawObliquePolygon ( dc, x1, y1, x2, yy2, m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)); else { DrawObliquePolygon ( dc, x1, y1, x2, yy2, 5); DrawObliquePolygon ( dc, x1, y5, x2, y2, -5); } DrawVerticalLine ( dc,y3,y4,x2,m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)); //cloture flagStemHeighte View::s_drawingLigObliqua = false; // queue_lig = OFF; //desamorce alg.queue DUR_BR } } if (note->m_lig) // memoriser positions d'une note a l'autre; relier notes par barres { *(View::s_drawingLigX+1) = x2; *(View::s_drawingLigY+1) = y; // relie notes ligaturees par barres flagStemHeightes //if (in(x1,(*View::s_drawingLigX)-2,(*View::s_drawingLigX)+2) || (this->fligat && this->lat && !Note1::marq_obl)) // les dernieres conditions pour permettre ligature flagStemHeighte ancienne // DrawVerticalLine (dc, *ligat_y, y1, (this->fligat && this->lat) ? x2: x1, m_doc->m_parameters.m_stemWidth); // ax2 - drawing flagStemHeight lines missing *View::s_drawingLigX = *(View::s_drawingLigX + 1); *View::s_drawingLigY = *(View::s_drawingLigY + 1); } y3 = y2 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; if (note->m_lig) { if (note->m_dur == DUR_BR) // && this->queue_lig) // queue gauche bas: DUR_BR initiale descendante // ax2 - no support of queue_lig (see WG corrigeLigature) { DrawVerticalLine ( dc, y2, y3, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } else if (note->m_dur == DUR_LG) // && !this->queue_lig) // DUR_LG en ligature, queue droite bas // ax2 - no support of queue_lig { DrawVerticalLine (dc, y2, y3, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } else if (note->m_dur == DUR_1) // && this->queue_lig ) // queue gauche haut // ax2 - no support of queue_lig { y2 = y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; DrawVerticalLine ( dc, y1, y2, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } } else if (note->m_dur == DUR_LG) // DUR_LG isolee: queue comme notes normales */ if (note->GetActualDur() == DUR_LG) { verticalCenter = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)*2; // ENZ up = (y < verticalCenter) ? ON : OFF; // ENZ if ( note->GetDrawingStemDir() != STEMDIRECTION_NONE ) { if ( note->GetDrawingStemDir() == STEMDIRECTION_up) { up = ON; } else { up = OFF; } } if (!up) { y3 = y1 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*8; y2 = y1; } else { y3 = y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; y2 = y1; } DrawVerticalLine ( dc, y2,y3,x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } return; }
void View::DrawMaximaToBrevis( DeviceContext *dc, int y, LayerElement *element, Layer *layer, Staff *staff ) { assert( dc ); assert( element ); assert( layer ); assert( staff ); Note *note = dynamic_cast<Note*>(element); assert( note ); int xn, x1, x2, y1, y2, y3, y4; // int yy2, y5; // unused int verticalCenter, up, height; height = m_doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, false) / 2 ; xn = element->GetDrawingX(); // calcul des dimensions du rectangle x1 = xn - m_doc->GetDrawingBrevisWidth( staff->m_drawingStaffSize ); x2 = xn + m_doc->GetDrawingBrevisWidth( staff->m_drawingStaffSize ); if (note->GetActualDur() == DUR_MX) { x1 -= m_doc->GetDrawingBrevisWidth( staff->m_drawingStaffSize ); x2 += m_doc->GetDrawingBrevisWidth( staff->m_drawingStaffSize ); } y1 = y + m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 = y - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y3 = (int)(y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)/2); // partie d'encadrement qui depasse y4 = (int)(y2 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)/2); if (note->GetColored()!=BOOLEAN_true) { // double base des carrees DrawObliquePolygon ( dc, x1, y1, x2, y1, -height ); DrawObliquePolygon ( dc, x1, y2, x2, y2, height ); } else { DrawFullRectangle( dc,x1,y1,x2,y2); } DrawVerticalLine ( dc, y3, y4, x1, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); // corset lateral DrawVerticalLine ( dc, y3, y4, x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); // stem if (note->GetActualDur() < DUR_BR) { verticalCenter = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)*2; up = (y < verticalCenter) ? true : false; if ( note->GetDrawingStemDir() != STEMDIRECTION_NONE ) { if ( note->GetDrawingStemDir() == STEMDIRECTION_up) { up = true; } else { up = false; } } if (!up) { y3 = y1 - m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*8; y2 = y1; } else { y3 = y1 + m_doc->GetDrawingUnit(staff->m_drawingStaffSize)*6; y2 = y1; } DrawVerticalLine ( dc, y2,y3,x2, m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize) ); } return; }
void View::DrawMensuralNote ( DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff, Measure *measure ) { assert( dc ); assert( element ); assert( layer ); assert( staff ); assert( measure ); Note *note = dynamic_cast<Note*>(element); assert( note ); int staffSize = staff->m_drawingStaffSize; int noteY = element->GetDrawingY(); int xLedger, xNote, xStem; int drawingDur; bool drawingCueSize; int staffY = staff->GetDrawingY(); wchar_t fontNo; int ledge; int verticalCenter = 0; xStem = element->GetDrawingX(); xLedger = xStem; drawingDur = note->GetDrawingDur(); drawingCueSize = note->HasGrace(); int radius = m_doc->GetGlyphWidth(SMUFL_E0A3_noteheadHalf, staffSize, drawingCueSize); if (drawingDur > DUR_1 || (drawingDur == DUR_1 && staff->notAnc)) { // annuler provisoirement la modif. des lignes addit. ledge = m_doc->GetDrawingLedgerLineLength(staffSize, drawingCueSize); } else { ledge = m_doc->GetDrawingLedgerLineLength(staffSize, drawingCueSize); radius += radius/3; } /************** Stem/notehead direction: **************/ verticalCenter = staffY - m_doc->GetDrawingDoubleUnit(staffSize)*2; data_STEMDIRECTION noteStemDir = note->CalcDrawingStemDir(); if ( noteStemDir != STEMDIRECTION_NONE ) { note->SetDrawingStemDir( noteStemDir ); } else if ( layer->GetDrawingStemDir() != STEMDIRECTION_NONE) { note->SetDrawingStemDir( layer->GetDrawingStemDir() ); } else { note->SetDrawingStemDir((noteY >= verticalCenter) ? STEMDIRECTION_down : STEMDIRECTION_up); } xNote = xStem - radius; /************** Noteheads: **************/ // Long, breve and ligatures if ((note->GetLig()!=LIGATURE_NONE) && (drawingDur <= DUR_1)) { DrawLigature ( dc, noteY, element, layer, staff); } else if (drawingDur < DUR_1) { DrawMaximaToBrevis( dc, noteY, element, layer, staff); } else if (drawingDur == DUR_1) { if (note->GetColored()) fontNo = SMUFL_E938_mensuralNoteheadSemibrevisBlack; else fontNo = SMUFL_E939_mensuralNoteheadSemibrevisVoid; DrawSmuflCode( dc, xNote, noteY, fontNo, staff->m_drawingStaffSize, drawingCueSize ); } // Other values ??WE WANT MENSURAL NOTEHEADS, NOT CMN!!!!!!!! else { if (note->GetColored()) { if (drawingDur == DUR_2) fontNo = SMUFL_E0A4_noteheadBlack; else fontNo = SMUFL_E0A3_noteheadHalf; } else { if (drawingDur > DUR_2) fontNo = SMUFL_E0A4_noteheadBlack; else fontNo = SMUFL_E0A3_noteheadHalf; } DrawSmuflCode( dc, xNote, noteY, fontNo, staff->m_drawingStaffSize, drawingCueSize ); DrawStem(dc, note, staff, note->GetDrawingStemDir(), radius, xStem, noteY); } /************** Ledger lines: **************/ int staffTop = staffY + m_doc->GetDrawingUnit(staffSize); int staffBot = staffY - m_doc->GetDrawingStaffSize(staffSize) - m_doc->GetDrawingUnit(staffSize); //if the note is not in the staff if (!is_in(noteY,staffTop,staffBot)) { int distance, highestNewLine, numLines; bool aboveStaff = (noteY > staffTop); distance = (aboveStaff ? (noteY - staffY) : staffY - m_doc->GetDrawingStaffSize(staffSize) - noteY); highestNewLine = ((distance % m_doc->GetDrawingDoubleUnit(staffSize) > 0) ? (distance - m_doc->GetDrawingUnit(staffSize)) : distance); numLines = highestNewLine / m_doc->GetDrawingDoubleUnit(staffSize); DrawLedgerLines(dc, note, staff, aboveStaff, false, 0, numLines); } /************** dots **************/ if (note->GetDots()) { int xDot; if (note->GetDur() < DUR_2 || (note->GetDur() > DUR_8 && (note->GetDrawingStemDir() == STEMDIRECTION_up))) xDot = xStem + m_doc->GetDrawingUnit(staffSize)*7/2; else xDot = xStem + m_doc->GetDrawingUnit(staffSize)*5/2; DrawDots( dc, xDot, noteY, note->GetDots(), staff ); } }