static void addText(Score* score, int subtype, const QString& s) { MeasureBase* measure = score->first(); if (measure == 0 || measure->type() != VBOX) { score->insertMeasure(VBOX, measure); measure = score->first(); } Text* text = new Text(score); switch(subtype) { case TEXT_TITLE: text->setTextStyleType(TEXT_STYLE_TITLE); break; case TEXT_SUBTITLE: text->setTextStyleType(TEXT_STYLE_SUBTITLE); break; case TEXT_COMPOSER: text->setTextStyleType(TEXT_STYLE_COMPOSER); break; case TEXT_POET: text->setTextStyleType(TEXT_STYLE_POET); break; } text->setParent(measure); text->setText(s); score->undoAddElement(text); }
void Page::doRebuildBspTree() { int n = 0; scanElements(&n, countElements, false); QRectF r; if (score()->layoutMode() == LayoutMode::LINE) { qreal w = 0.0; qreal h = 0.0; if (!_systems.empty()) { h = _systems.front()->height(); if (!_systems.front()->measures().empty()) { MeasureBase* mb = _systems.front()->measures().back(); w = mb->x() + mb->width(); } } r = QRectF(0.0, 0.0, w, h); } else r = abbox(); bspTree.initialize(r, n); scanElements(&bspTree, &bspInsert, false); bspTreeValid = true; }
void Page::doRebuildBspTree() { QList<Element*> el; for (System* s : _systems) { for (MeasureBase* m : s->measures()) m->scanElements(&el, collectElements, false); } scanElements(&el, collectElements, false); int n = el.size(); if (score()->layoutMode() == LayoutMode::LINE) { if (_systems.isEmpty()) return; if (_systems.front()->measures().isEmpty()) return; qreal h = _systems.front()->height(); MeasureBase* mb = _systems.front()->measures().back(); qreal w = mb->x() + mb->width(); bspTree.initialize(QRectF(0.0, 0.0, w, h), n); } else bspTree.initialize(abbox(), n); for (int i = 0; i < n; ++i) bspTree.insert(el.at(i)); bspTreeValid = true; }
Measure* MeasureBase::nextMeasure() const { MeasureBase* m = _next; for (;;) { if (m == 0 || m->isMeasure()) break; m = m->_next; } return toMeasure(m); }
Measure* MeasureBase::prevMeasure() const { MeasureBase* m = prev(); while (m) { if (m->isMeasure()) return toMeasure(m); m = m->prev(); } return 0; }
int MeasureBase::index() const { int idx = 0; MeasureBase* m = score()->first(); while (m) { if (m == this) return idx; m = m->next(); } return -1; }
MeasureBase* Score::tick2measureBase(int tick) const { for (MeasureBase* mb = first(); mb; mb = mb->next()) { int st = mb->tick(); int l = mb->ticks(); if (tick >= st && tick < (st+l)) return mb; } // qDebug("tick2measureBase %d not found\n", tick); return 0; }
Segment* Segment::prev1() const { if (prev()) return prev(); MeasureBase* m = measure(); for (;;) { m = m->prev(); if (m == 0) return 0; if (m->type() == MEASURE) return static_cast<Measure*>(m)->last(); } }
Segment* Segment::next1() const { if (next()) return next(); MeasureBase* m = measure(); for (;;) { m = m->next(); if (m == 0) return 0; if (m->type() == MEASURE) return static_cast<Measure*>(m)->first(); } }
void addTitleToScore(Score *score, const QString &string, int textCounter) { Text* text = new Text(score); if (textCounter == 1) text->setSubStyle(SubStyle::TITLE); else if (textCounter == 2) text->setSubStyle(SubStyle::COMPOSER); text->setPlainText(string.right(string.size() - TEXT_PREFIX.size())); MeasureBase* measure = score->first(); if (measure->type() != Element::Type::VBOX) { measure = new VBox(score); measure->setTick(0); measure->setNext(score->first()); score->measures()->add(measure); } measure->add(text); }
ChordRest* Score::nextMeasure(ChordRest* element, bool selectBehavior) { if (!element) return 0; MeasureBase* mb = element->measure()->next(); while (mb && ((mb->type() != Element::MEASURE) || (mb->type() == Element::MEASURE && static_cast<Measure*>(mb)->multiMeasure() < 0))) mb = mb->next(); Measure* measure = static_cast<Measure*>(mb); int endTick = element->measure()->last()->nextChordRest(element->track(), true)->tick(); bool last = false; if (selection().state() == SEL_RANGE) { if (element->tick() != endTick && selection().tickEnd() <= endTick) { measure = element->measure(); last = true; } else if (element->tick() == endTick && selection().isEndActive()) last = true; } else if (element->tick() != endTick && selectBehavior) { measure = element->measure(); last = true; } if (!measure) { measure = element->measure(); last = true; } int staff = element->staffIdx(); Segment* startSeg = last ? measure->last() : measure->first(); for (Segment* seg = startSeg; seg; seg = last ? seg->prev() : seg->next()) { int etrack = (staff+1) * VOICES; for (int track = staff * VOICES; track < etrack; ++track) { Element* pel = seg->element(track); if (pel && pel->isChordRest()) return static_cast<ChordRest*>(pel); } } return 0; }
Measure* MeasureBase::prevMeasureMM() const { MeasureBase* m = prev(); while (m) { if (m->isMeasure()) { Measure* mm = toMeasure(m); if (score()->styleB(StyleIdx::createMultiMeasureRests)) { if (mm->mmRestCount() >= 0) { if (mm->hasMMRest()) return mm->mmRest(); return mm; } } else return mm; } m = m->prev(); } return 0; }
void addTitleToScore(Score *score, const QString &string, int textCounter) { Tid ssid = Tid::DEFAULT; if (textCounter == 1) ssid = Tid::TITLE; else if (textCounter == 2) ssid = Tid::COMPOSER; Text* text = new Text(score, ssid); text->setPlainText(string.right(string.size() - int(TEXT_PREFIX.size()))); MeasureBase* measure = score->first(); if (!measure->isVBox()) { measure = new VBox(score); measure->setTick(0); measure->setNext(score->first()); score->measures()->add(measure); } measure->add(text); }
void Part::setStaves(int n) { int ns = _staves.size(); if (n < ns) { printf("Part::setStaves(): remove staves not implemented!\n"); return; } int staffIdx = _score->staffIdx(this) + ns; for (int i = ns; i < n; ++i) { Staff* staff = new Staff(_score, this, i); _staves.push_back(staff); _score->staves().insert(staffIdx, staff); for (MeasureBase* mb = _score->first(); mb; mb = mb->next()) { if (mb->type() != MEASURE) continue; Measure* m = static_cast<Measure*>(mb); m->insertStaff(staff, staffIdx); } ++staffIdx; } }
void addTitle(Score *score, const QString &string, int *textCounter) { if (string.left(TEXT_PREFIX.size()) == QString::fromStdString(TEXT_PREFIX)) { ++*textCounter; Text* text = new Text(score); if (*textCounter == 1) text->setTextStyleType(TextStyleType::TITLE); else if (*textCounter == 2) text->setTextStyleType(TextStyleType::COMPOSER); text->setText(string.right(string.size() - TEXT_PREFIX.size())); MeasureBase* measure = score->first(); if (measure->type() != Element::Type::VBOX) { measure = new VBox(score); measure->setTick(0); measure->setNext(score->first()); score->measures()->add(measure); } measure->add(text); } }
void PlayPanel::setScore(Score* s) { if (cs != 0 && cs == s) return; cs = s; if (cs) { MeasureBase* lm = cs->last(); if (lm) setEndpos(lm->tick() + lm->ticks()); } bool enable = cs != 0; volumeSlider->setEnabled(enable); posSlider->setEnabled(enable); tempoSlider->setEnabled(enable); swingStyle->setEnabled(enable); if (cs) { setTempo(cs->tempomap()->tempo(0)); setRelTempo(cs->tempomap()->relTempo()); Measure* m = cs->lastMeasure(); if (m) setEndpos(m ? m->tick() + m->ticks() : 0); int tick = cs->playPos(); heartBeat(tick, tick); } else { setTempo(120.0); setRelTempo(1.0); setEndpos(0); heartBeat(0, 0); } // heartBeat2(seq->getCurTime()); // int tick, utick; // seq->getCurTick(&tick, &utick); // heartBeat(tick, utick); update(); }
void Score::readStaff(XmlReader& e) { int staff = e.intAttribute("id", 1) - 1; int measureIdx = 0; e.setCurrentMeasureIndex(0); e.initTick(0); e.setTrack(staff * VOICES); if (staff == 0) { while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "Measure") { Measure* measure = 0; measure = new Measure(this); measure->setTick(e.tick()); e.setCurrentMeasureIndex(measureIdx++); // // inherit timesig from previous measure // Measure* m = e.lastMeasure(); // measure->prevMeasure(); Fraction f(m ? m->timesig() : Fraction(4,4)); measure->setLen(f); measure->setTimesig(f); measure->read(e, staff); measure->checkMeasure(staff); if (!measure->isMMRest()) { measures()->add(measure); e.setLastMeasure(measure); e.initTick(measure->tick() + measure->ticks()); } else { // this is a multi measure rest // always preceded by the first measure it replaces Measure* m1 = e.lastMeasure(); if (m1) { m1->setMMRest(measure); measure->setTick(m1->tick()); } } } else if (tag == "HBox" || tag == "VBox" || tag == "TBox" || tag == "FBox") { MeasureBase* mb = toMeasureBase(Element::name2Element(tag, this)); mb->read(e); mb->setTick(e.tick()); measures()->add(mb); } else if (tag == "tick") e.initTick(fileDivision(e.readInt())); else e.unknown(); } } else { Measure* measure = firstMeasure(); while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "Measure") { if (measure == 0) { qDebug("Score::readStaff(): missing measure!"); measure = new Measure(this); measure->setTick(e.tick()); measures()->add(measure); } e.initTick(measure->tick()); e.setCurrentMeasureIndex(measureIdx++); measure->read(e, staff); measure->checkMeasure(staff); if (measure->isMMRest()) measure = e.lastMeasure()->nextMeasure(); else { e.setLastMeasure(measure); if (measure->mmRest()) measure = measure->mmRest(); else measure = measure->nextMeasure(); } } else if (tag == "tick") e.initTick(fileDivision(e.readInt())); else e.unknown(); } } }
void Score::write(Xml& xml, bool selectionOnly) { // if we have multi measure rests and some parts are hidden, // then some layout information is missing: // relayout with all parts set visible QList<Part*> hiddenParts; bool unhide = false; if (styleB(StyleIdx::createMultiMeasureRests)) { for (Part* part : _parts) { if (!part->show()) { if (!unhide) { startCmd(); unhide = true; } part->undoChangeProperty(P_ID::VISIBLE, true); hiddenParts.append(part); } } } if (unhide) { doLayout(); for (Part* p : hiddenParts) p->setShow(false); } xml.stag("Score"); switch(_layoutMode) { case LayoutMode::PAGE: case LayoutMode::FLOAT: case LayoutMode::SYSTEM: break; case LayoutMode::LINE: xml.tag("layoutMode", "line"); break; } #ifdef OMR if (_omr && xml.writeOmr) _omr->write(xml); #endif if (_showOmr && xml.writeOmr) xml.tag("showOmr", _showOmr); if (_audio && xml.writeOmr) { xml.tag("playMode", int(_playMode)); _audio->write(xml); } for (int i = 0; i < 32; ++i) { if (!_layerTags[i].isEmpty()) { xml.tag(QString("LayerTag id=\"%1\" tag=\"%2\"").arg(i).arg(_layerTags[i]), _layerTagComments[i]); } } int n = _layer.size(); for (int i = 1; i < n; ++i) { // dont save default variant const Layer& l = _layer[i]; xml.tagE(QString("Layer name=\"%1\" mask=\"%2\"").arg(l.name).arg(l.tags)); } xml.tag("currentLayer", _currentLayer); if (!MScore::testMode) _synthesizerState.write(xml); if (pageNumberOffset()) xml.tag("page-offset", pageNumberOffset()); xml.tag("Division", MScore::division); xml.curTrack = -1; _style.save(xml, true); // save only differences to buildin style xml.tag("showInvisible", _showInvisible); xml.tag("showUnprintable", _showUnprintable); xml.tag("showFrames", _showFrames); xml.tag("showMargins", _showPageborders); QMapIterator<QString, QString> i(_metaTags); while (i.hasNext()) { i.next(); if ((!MScore::testMode && !MScore::saveTemplateMode) || (i.key() != "platform" && i.key() != "creationDate")) xml.tag(QString("metaTag name=\"%1\"").arg(i.key().toHtmlEscaped()), i.value()); } if (!selectionOnly) { xml.stag("PageList"); foreach(Page* page, _pages) page->write(xml); xml.etag(); } xml.curTrack = 0; int staffStart; int staffEnd; MeasureBase* measureStart; MeasureBase* measureEnd; if (selectionOnly) { staffStart = _selection.staffStart(); staffEnd = _selection.staffEnd(); // make sure we select full parts Staff* sStaff = staff(staffStart); Part* sPart = sStaff->part(); Staff* eStaff = staff(staffEnd - 1); Part* ePart = eStaff->part(); staffStart = staffIdx(sPart); staffEnd = staffIdx(ePart) + ePart->nstaves(); measureStart = _selection.startSegment()->measure(); if (_selection.endSegment()) measureEnd = _selection.endSegment()->measure()->next(); else measureEnd = 0; } else { staffStart = 0; staffEnd = nstaves(); measureStart = first(); measureEnd = 0; } foreach(const Part* part, _parts) { if (!selectionOnly || ((staffIdx(part) >= staffStart) && (staffEnd >= staffIdx(part) + part->nstaves()))) part->write(xml); } xml.curTrack = 0; xml.trackDiff = -staffStart * VOICES; if (measureStart) { for (int staffIdx = staffStart; staffIdx < staffEnd; ++staffIdx) { xml.stag(QString("Staff id=\"%1\"").arg(staffIdx + 1 - staffStart)); xml.curTick = measureStart->tick(); xml.tickDiff = xml.curTick; xml.curTrack = staffIdx * VOICES; bool writeSystemElements = staffIdx == staffStart; for (MeasureBase* m = measureStart; m != measureEnd; m = m->next()) writeMeasure(xml, m, staffIdx, writeSystemElements); xml.etag(); } } xml.curTrack = -1; if (!selectionOnly) { for (const Excerpt* excerpt : _excerpts) { if (excerpt->partScore() != this) excerpt->partScore()->write(xml, false); // recursion } } if (parentScore()) xml.tag("name", name()); xml.etag(); if (unhide) { endCmd(); undo()->undo(); endUndoRedo(); } }
void MTrack::processMeta(int tick, const MidiEvent& mm) { if (!staff) { qDebug("processMeta: no staff"); return; } const uchar* data = (uchar*)mm.edata(); int staffIdx = staff->idx(); Score* cs = staff->score(); switch (mm.metaType()) { case META_TEXT: case META_LYRIC: { QString s((char*)data); cs->addLyrics(tick, staffIdx, s); } break; case META_TRACK_NAME: name = (const char*)data; break; case META_TEMPO: { unsigned tempo = data[2] + (data[1] << 8) + (data[0] <<16); double t = 1000000.0 / double(tempo); cs->setTempo(tick, t); // TODO: create TempoText } break; case META_KEY_SIGNATURE: { int key = ((const char*)data)[0]; if (key < -7 || key > 7) { qDebug("ImportMidi: illegal key %d", key); break; } KeySigEvent ks; ks.setAccidentalType(key); (*staff->keymap())[tick] = ks; hasKey = true; } break; case META_COMPOSER: // mscore extension case META_POET: case META_TRANSLATOR: case META_SUBTITLE: case META_TITLE: { Text* text = new Text(cs); switch(mm.metaType()) { case META_COMPOSER: text->setTextStyleType(TEXT_STYLE_COMPOSER); break; case META_TRANSLATOR: text->setTextStyleType(TEXT_STYLE_TRANSLATOR); break; case META_POET: text->setTextStyleType(TEXT_STYLE_POET); break; case META_SUBTITLE: text->setTextStyleType(TEXT_STYLE_SUBTITLE); break; case META_TITLE: text->setTextStyleType(TEXT_STYLE_TITLE); break; } text->setText((const char*)(mm.edata())); MeasureBase* measure = cs->first(); if (measure->type() != Element::VBOX) { measure = new VBox(cs); measure->setTick(0); measure->setNext(cs->first()); cs->add(measure); } measure->add(text); } break; case META_COPYRIGHT: cs->setMetaTag("Copyright", QString((const char*)(mm.edata()))); break; case META_TIME_SIGNATURE: qDebug("midi: meta timesig: %d, division %d", tick, MScore::division); cs->sigmap()->add(tick, Fraction(data[0], 1 << data[1])); break; default: if (MScore::debugMode) qDebug("unknown meta type 0x%02x", mm.metaType()); break; } }
void System::layout2() { if (isVbox()) // ignore vbox return; int nstaves = _staves.size(); qreal _spatium = spatium(); qreal y = 0.0; int lastStaffIdx = 0; // last visible staff int firstStaffIdx = -1; qreal lastStaffDistanceDown = 0.0; for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { Staff* staff = score()->staff(staffIdx); StyleIdx downDistance; qreal userDist = 0.0; if ((staffIdx + 1) == nstaves) { // // last staff in system // MeasureBase* mb = ml.last(); bool nextMeasureIsVBOX = false; if (mb->next()) { Element::Type type = mb->next()->type(); if (type == Element::Type::VBOX || type == Element::Type::TBOX || type == Element::Type::FBOX) nextMeasureIsVBOX = true; } downDistance = nextMeasureIsVBOX ? StyleIdx::systemFrameDistance : StyleIdx::minSystemDistance; } else if (staff->rstaff() < (staff->part()->staves()->size()-1)) { // // staff is not last staff in a part // downDistance = StyleIdx::akkoladeDistance; userDist = score()->staff(staffIdx + 1)->userDist(); } else { downDistance = StyleIdx::staffDistance; userDist = score()->staff(staffIdx + 1)->userDist(); } SysStaff* s = _staves[staffIdx]; qreal distDown = score()->styleS(downDistance).val() * _spatium + userDist; qreal nominalDistDown = distDown; qreal distUp = 0.0; int n = ml.size(); for (int i = 0; i < n; ++i) { MeasureBase* m = ml.at(i); distDown = qMax(distDown, m->distanceDown(staffIdx)); distUp = qMax(distUp, m->distanceUp(staffIdx)); } s->setDistanceDown(distDown); s->setDistanceUp(distUp); if (!staff->show() || !s->show()) { s->setbbox(QRectF()); // already done in layout() ? continue; } qreal sHeight = staff->height(); qreal dup = staffIdx == 0 ? 0.0 : s->distanceUp(); if (staff->lines() == 1) dup -= _spatium * staff->mag(); s->bbox().setRect(_leftMargin, y + dup, width() - _leftMargin, sHeight); y += dup + sHeight + s->distanceDown(); lastStaffIdx = staffIdx; lastStaffDistanceDown = distDown - nominalDistDown; if (firstStaffIdx == -1) firstStaffIdx = staffIdx; } if (firstStaffIdx == -1) firstStaffIdx = 0; qreal systemHeight = staff(lastStaffIdx)->bbox().bottom(); if (lastStaffIdx < nstaves - 1) systemHeight += lastStaffDistanceDown; setHeight(systemHeight); int n = ml.size(); for (int i = 0; i < n; ++i) { MeasureBase* m = ml.at(i); if (m->type() == Element::Type::MEASURE) { // note that the factor 2 * _spatium must be corrected for when exporting // system distance in MusicXML (issue #24733) m->bbox().setRect(0.0, -_spatium, m->width(), systemHeight + 2 * _spatium); } else if (m->type() == Element::Type::HBOX) { m->bbox().setRect(0.0, 0.0, m->width(), systemHeight); static_cast<HBox*>(m)->layout2(); } } if (_barLine) { _barLine->setTrack(firstStaffIdx * VOICES); _barLine->setSpan(lastStaffIdx - firstStaffIdx + 1); if (score()->staff(0)->lines() == 1) _barLine->setSpanFrom(BARLINE_SPAN_1LINESTAFF_FROM); int spanTo = (score()->staff(lastStaffIdx)->lines() == 1) ? BARLINE_SPAN_1LINESTAFF_TO : (score()->staff(lastStaffIdx)->lines()-1)*2; _barLine->setSpanTo(spanTo); _barLine->layout(); } //--------------------------------------------------- // layout brackets vertical position //--------------------------------------------------- n = _brackets.size(); for (int i = 0; i < n; ++i) { Bracket* b = _brackets.at(i); int staffIdx1 = b->firstStaff(); int staffIdx2 = b->lastStaff(); qreal sy = 0; // assume bracket not visible qreal ey = 0; // if start staff not visible, try next staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx1]->show()) ++staffIdx1; // if end staff not visible, try prev staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx2]->show()) --staffIdx2; // the bracket will be shown IF: // it spans at least 2 visible staves (staffIdx1 < staffIdx2) OR // it spans just one visible staff (staffIdx1 == staffIdx2) but it is required to do so // (the second case happens at least when the bracket is initially dropped) bool notHidden = (staffIdx1 < staffIdx2) || (b->span() == 1 && staffIdx1 == staffIdx2); if (notHidden) { // set vert. pos. and height to visible spanned staves sy = _staves[staffIdx1]->bbox().top(); ey = _staves[staffIdx2]->bbox().bottom(); } b->rypos() = sy; b->setHeight(ey - sy); b->layout(); } //--------------------------------------------------- // layout instrument names //--------------------------------------------------- int staffIdx = 0; n = score()->parts().size(); for (Part* p : score()->parts()) { SysStaff* s = staff(staffIdx); SysStaff* s2; int nstaves = p->nstaves(); if (s->show()) { for (InstrumentName* t : s->instrumentNames) { // // override Text->layout() // qreal y1, y2; switch (t->layoutPos()) { default: case 0: // center at part y1 = s->bbox().top(); s2 = staff(staffIdx); for (int i = staffIdx + nstaves - 1; i > 0; --i) { SysStaff* s = staff(i); if (s->show()) { s2 = s; break; } } y2 = s2->bbox().bottom(); break; case 1: // center at first staff y1 = s->bbox().top(); y2 = s->bbox().bottom(); break; // TODO: // sort out invisible staves case 2: // center between first and second staff y1 = s->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 3: // center at second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 4: // center between first and second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; case 5: // center at third staff y1 = staff(staffIdx + 2)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; } t->rypos() = y1 + (y2 - y1) * .5 + t->textStyle().offset(t->spatium()).y(); } } staffIdx += nstaves; } }
Score::FileError Score::read114(XmlReader& e) { if (parentScore()) setMscVersion(parentScore()->mscVersion()); for (unsigned int i = 0; i < sizeof(style114)/sizeof(*style114); ++i) style()->set(style114[i].idx, style114[i].val); // old text style defaults TextStyle ts = style()->textStyle("Chord Symbol"); ts.setYoff(-4.0); style()->setTextStyle(ts); TempoMap tm; while (e.readNextStartElement()) { e.setTrack(-1); const QStringRef& tag(e.name()); if (tag == "Staff") readStaff(e); else if (tag == "KeySig") { // not supported KeySig* ks = new KeySig(this); ks->read(e); // customKeysigs.append(ks); delete ks; } else if (tag == "siglist") _sigmap->read(e, _fileDivision); else if (tag == "programVersion") { _mscoreVersion = e.readElementText(); parseVersion(_mscoreVersion); } else if (tag == "programRevision") _mscoreRevision = e.readInt(); else if (tag == "Mag" || tag == "MagIdx" || tag == "xoff" || tag == "Symbols" || tag == "cursorTrack" || tag == "yoff") e.skipCurrentElement(); // obsolete else if (tag == "tempolist") { // store the tempo list to create invisible tempo text later qreal tempo = e.attribute("fix","2.0").toDouble(); tm.setRelTempo(tempo); while (e.readNextStartElement()) { if (e.name() == "tempo") { int tick = e.attribute("tick").toInt(); double tmp = e.readElementText().toDouble(); tick = (tick * MScore::division + _fileDivision/2) / _fileDivision; auto pos = tm.find(tick); if (pos != tm.end()) tm.erase(pos); tm.setTempo(tick, tmp); } else if (e.name() == "relTempo") e.readElementText(); else e.unknown(); } } else if (tag == "playMode") _playMode = PlayMode(e.readInt()); else if (tag == "SyntiSettings") _synthesizerState.read(e); else if (tag == "Spatium") _style.setSpatium (e.readDouble() * MScore::DPMM); else if (tag == "Division") _fileDivision = e.readInt(); else if (tag == "showInvisible") _showInvisible = e.readInt(); else if (tag == "showFrames") _showFrames = e.readInt(); else if (tag == "showMargins") _showPageborders = e.readInt(); else if (tag == "Style") { qreal sp = _style.spatium(); _style.load(e); // adjust this now so chords render properly on read // other style adjustments can wait until reading is finished if (style(StyleIdx::useGermanNoteNames).toBool()) style()->set(StyleIdx::useStandardNoteNames, false); if (_layoutMode == LayoutMode::FLOAT) { // style should not change spatium in // float mode _style.setSpatium(sp); } } else if (tag == "TextStyle") { TextStyle s; s.read(e); qreal spMM = _style.spatium() / MScore::DPMM; if (s.frameWidthMM() != 0.0) s.setFrameWidth(Spatium(s.frameWidthMM() / spMM)); if (s.paddingWidthMM() != 0.0) s.setPaddingWidth(Spatium(s.paddingWidthMM() / spMM)); \ // convert 1.2 text styles s.setName(convertOldTextStyleNames(s.name())); if (s.name() == "Lyrics Odd Lines" || s.name() == "Lyrics Even Lines") s.setAlign((s.align() & ~ Align(AlignmentFlags::VMASK)) | AlignmentFlags::BASELINE); _style.setTextStyle(s); } else if (tag == "page-layout") { if (_layoutMode != LayoutMode::FLOAT && _layoutMode != LayoutMode::SYSTEM) { PageFormat pf; pf.copy(*pageFormat()); pf.read(e, this); setPageFormat(pf); } else e.skipCurrentElement(); } else if (tag == "copyright" || tag == "rights") { Text* text = new Text(this); text->read(e); text->layout(); setMetaTag("copyright", text->plainText()); delete text; } else if (tag == "movement-number") setMetaTag("movementNumber", e.readElementText()); else if (tag == "movement-title") setMetaTag("movementTitle", e.readElementText()); else if (tag == "work-number") setMetaTag("workNumber", e.readElementText()); else if (tag == "work-title") setMetaTag("workTitle", e.readElementText()); else if (tag == "source") setMetaTag("source", e.readElementText()); else if (tag == "metaTag") { QString name = e.attribute("name"); setMetaTag(name, e.readElementText()); } else if (tag == "Part") { Part* part = new Part(this); part->read114(e); _parts.push_back(part); } else if (tag == "Slur") { Slur* slur = new Slur(this); slur->read(e); addSpanner(slur); } else if ((tag == "HairPin") || (tag == "Ottava") || (tag == "TextLine") || (tag == "Volta") || (tag == "Trill") || (tag == "Pedal")) { Spanner* s = static_cast<Spanner*>(Element::name2Element(tag, this)); s->read(e); if (s->track() == -1) s->setTrack(e.track()); else e.setTrack(s->track()); // update current track if (s->tick() == -1) s->setTick(e.tick()); else e.initTick(s->tick()); // update current tick if (s->track2() == -1) s->setTrack2(s->track()); if (s->ticks() == 0) { delete s; qDebug("zero spanner %s ticks: %d", s->name(), s->ticks()); } else { addSpanner(s); } } else if (tag == "Excerpt") { if (MScore::noExcerpts) e.skipCurrentElement(); else { Excerpt* ex = new Excerpt(this); ex->read(e); _excerpts.append(ex); } } else if (tag == "Beam") { Beam* beam = new Beam(this); beam->read(e); beam->setParent(0); // _beams.append(beam); } else if (tag == "name") setName(e.readElementText()); else e.unknown(); } if (e.error() != XmlStreamReader::NoError) return FileError::FILE_BAD_FORMAT; int n = nstaves(); for (int idx = 0; idx < n; ++idx) { Staff* s = _staves[idx]; int track = idx * VOICES; // check barLineSpan if (s->barLineSpan() > (n - idx)) { qDebug("read114: invalid bar line span %d (max %d)", s->barLineSpan(), n - idx); s->setBarLineSpan(n - idx); } for (auto i : e.clefs(idx)) { int tick = i.first; ClefType clefId = i.second; Measure* m = tick2measure(tick); if (!m) continue; if ((tick == m->tick()) && m->prevMeasure()) m = m->prevMeasure(); Segment* seg = m->getSegment(Segment::Type::Clef, tick); if (seg->element(track)) static_cast<Clef*>(seg->element(track))->setGenerated(false); else { Clef* clef = new Clef(this); clef->setClefType(clefId); clef->setTrack(track); clef->setParent(seg); clef->setGenerated(false); seg->add(clef); } } // create missing KeySig KeyList* km = s->keyList(); for (auto i = km->begin(); i != km->end(); ++i) { int tick = i->first; if (tick < 0) { qDebug("read114: Key tick %d", tick); continue; } if (tick == 0 && i->second.key() == Key::C) continue; Measure* m = tick2measure(tick); if (!m) //empty score break; Segment* seg = m->getSegment(Segment::Type::KeySig, tick); if (seg->element(track)) static_cast<KeySig*>(seg->element(track))->setGenerated(false); else { KeySigEvent ke = i->second; KeySig* ks = new KeySig(this); ks->setKeySigEvent(ke); ks->setParent(seg); ks->setTrack(track); ks->setGenerated(false); seg->add(ks); } } } for (std::pair<int,Spanner*> p : spanner()) { Spanner* s = p.second; if (s->type() != Element::Type::SLUR) { if (s->type() == Element::Type::VOLTA) { Volta* volta = static_cast<Volta*>(s); volta->setAnchor(Spanner::Anchor::MEASURE); } } if (s->type() == Element::Type::OTTAVA || s->type() == Element::Type::PEDAL || s->type() == Element::Type::TRILL || s->type() == Element::Type::TEXTLINE) { qreal yo = 0; if (s->type() == Element::Type::OTTAVA) { // fix ottava position yo = styleS(StyleIdx::ottavaY).val() * spatium(); if (s->placement() == Element::Placement::BELOW) yo = -yo + s->staff()->height(); } else if (s->type() == Element::Type::PEDAL) { yo = styleS(StyleIdx::pedalY).val() * spatium(); } else if (s->type() == Element::Type::TRILL) { yo = styleS(StyleIdx::trillY).val() * spatium(); } else if (s->type() == Element::Type::TEXTLINE) { yo = -5.0 * spatium(); } if (!s->spannerSegments().isEmpty()) { for (SpannerSegment* seg : s->spannerSegments()) { if (!seg->userOff().isNull()) seg->setUserYoffset(seg->userOff().y() - yo); } } else { s->setUserYoffset(-yo); } } } connectTies(); // // remove "middle beam" flags from first ChordRest in // measure // for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) { int tracks = nstaves() * VOICES; bool first = true; for (int track = 0; track < tracks; ++track) { for (Segment* s = m->first(); s; s = s->next()) { if (s->segmentType() != Segment::Type::ChordRest) continue; ChordRest* cr = static_cast<ChordRest*>(s->element(track)); if (cr) { if(cr->type() == Element::Type::REST) { Rest* r = static_cast<Rest*>(cr); if (!r->userOff().isNull()) { int lineOffset = r->computeLineOffset(); qreal lineDist = r->staff() ? r->staff()->staffType()->lineDistance().val() : 1.0; r->rUserYoffset() -= (lineOffset * .5 * lineDist * r->spatium()); } } if(!first) { switch(cr->beamMode()) { case Beam::Mode::AUTO: case Beam::Mode::BEGIN: case Beam::Mode::END: case Beam::Mode::NONE: break; case Beam::Mode::MID: case Beam::Mode::BEGIN32: case Beam::Mode::BEGIN64: cr->setBeamMode(Beam::Mode::BEGIN); break; case Beam::Mode::INVALID: if (cr->type() == Element::Type::CHORD) cr->setBeamMode(Beam::Mode::AUTO); else cr->setBeamMode(Beam::Mode::NONE); break; } first = false; } } } } } for (MeasureBase* mb = _measures.first(); mb; mb = mb->next()) { if (mb->type() == Element::Type::VBOX) { Box* b = static_cast<Box*>(mb); qreal y = point(styleS(StyleIdx::staffUpperBorder)); b->setBottomGap(y); } } _fileDivision = MScore::division; // // sanity check for barLineSpan and update ottavas // foreach(Staff* staff, _staves) { int barLineSpan = staff->barLineSpan(); int idx = staffIdx(staff); int n = nstaves(); if (idx + barLineSpan > n) { qDebug("bad span: idx %d span %d staves %d", idx, barLineSpan, n); staff->setBarLineSpan(n - idx); } staff->updateOttava(); }