📄 notationhlayout.cpp
字号:
NOTATION_DEBUG << "NotationHLayout::preSquishBar: rate " << rate << endl; if (minRate < 0.0 || rate < minRate) minRate = rate; } else { NOTATION_DEBUG << "NotationHLayout::preSquishBar: not stretchy" << endl; } maxStretchy = std::max(maxStretchy, (*j)->stretchy); totalFixed = std::max(totalFixed, (*j)->fixed ) ; } NOTATION_DEBUG << "NotationHLayout::preSquishBar: minRate " << minRate << ", maxStretchy " << maxStretchy << ", totalFixed " << totalFixed << endl; // we have the rate from this point, but we want to assign // these elements an x coord based on the rate and distance // from the previous point, plus fixed space for this point // if it's a note (otherwise fixed space goes afterwards) if (i->first.subordering == 0) x += totalFixed; if (prevRate > 0.0) x += (time - prevTime) / prevRate; for (ChunkRefList::iterator j = list.begin(); j != list.end(); ++j) { NOTATION_DEBUG << "Setting x for time " << time << " to " << x << " in chunk at " << *j << endl; (*j)->x = x; } if (i->first.subordering != 0) x += totalFixed; prevTime = time; prevRate = minRate; } x += maxStretchy; for (BarDataMap::iterator mi = m_barData.begin(); mi != m_barData.end(); ++mi) { BarDataList &bdl = mi->second; BarDataList::iterator bdli = bdl.find(barNo); if (bdli != bdl.end()) { bdli->second.sizeData.idealWidth = bdli->second.sizeData.fixedWidth + x; if (!bdli->second.basicData.timeSignature.hasHiddenBars()) { bdli->second.sizeData.idealWidth += getBarMargin(); } else if (bdli->second.basicData.newTimeSig) { bdli->second.sizeData.idealWidth += getPostBarMargin(); } bdli->second.sizeData.reconciledWidth = bdli->second.sizeData.idealWidth; bdli->second.layoutData.needsLayout = true; } }}Staff *NotationHLayout::getStaffWithWidestBar(int barNo){ float maxWidth = -1; Staff *widest = 0; for (BarDataMap::iterator mi = m_barData.begin(); mi != m_barData.end(); ++mi) { BarDataList &list = mi->second; BarDataList::iterator li = list.find(barNo); if (li != list.end()) { NOTATION_DEBUG << "getStaffWithWidestBar: idealWidth is " << li->second.sizeData.idealWidth << endl; if (li->second.sizeData.idealWidth == 0.0) { NOTATION_DEBUG << "getStaffWithWidestBar(" << barNo << "): found idealWidth of zero, presquishing" << endl; preSquishBar(barNo); } if (li->second.sizeData.idealWidth > maxWidth) { maxWidth = li->second.sizeData.idealWidth; widest = mi->first; } } } return widest;}intNotationHLayout::getMaxRepeatedClefAndKeyWidth(int barNo){ int max = 0; timeT barStart = 0; for (BarDataMap::iterator mi = m_barData.begin(); mi != m_barData.end(); ++mi) { Staff *staff = mi->first; if (mi == m_barData.begin()) { barStart = staff->getSegment().getComposition()->getBarStart(barNo); } timeT t; int w = 0; Clef clef = staff->getSegment().getClefAtTime(barStart, t); if (t < barStart) w += m_npf->getClefWidth(clef); ::Rosegarden::Key key = staff->getSegment().getKeyAtTime(barStart, t); if (t < barStart) w += m_npf->getKeyWidth(key); if (w > max) max = w; } NOTATION_DEBUG << "getMaxRepeatedClefAndKeyWidth(" << barNo << "): " << max << endl; if (max > 0) return max + getFixedItemSpacing() * 2; else return 0;}voidNotationHLayout::reconcileBarsLinear(){ Profiler profiler("NotationHLayout::reconcileBarsLinear"); // Ensure that concurrent bars on all staffs have the same width, // which for now we make the maximum width required for this bar // on any staff. These days getStaffWithWidestBar actually does // most of the work in its call to preSquishBar, but this function // still sets the bar line positions etc. int barNo = getFirstVisibleBar(); m_totalWidth = 0.0; for (StaffIntMap::iterator i = m_staffNameWidths.begin(); i != m_staffNameWidths.end(); ++i) { if (i->second > m_totalWidth) m_totalWidth = double(i->second); } for (;;) { Staff *widest = getStaffWithWidestBar(barNo); if (!widest) { // have we reached the end of the piece? if (barNo >= getLastVisibleBar()) { // yes break; } else { m_totalWidth += m_spacing / 3; NOTATION_DEBUG << "Setting bar position for degenerate bar " << barNo << " to " << m_totalWidth << endl; m_barPositions[barNo] = m_totalWidth; ++barNo; continue; } } float maxWidth = m_barData[widest].find(barNo)->second.sizeData.idealWidth; if (m_pageWidth > 0.1 && maxWidth > m_pageWidth) { maxWidth = m_pageWidth; } NOTATION_DEBUG << "Setting bar position for bar " << barNo << " to " << m_totalWidth << endl; m_barPositions[barNo] = m_totalWidth; m_totalWidth += maxWidth; // Now apply width to this bar on all staffs for (BarDataMap::iterator i = m_barData.begin(); i != m_barData.end(); ++i) { BarDataList &list = i->second; BarDataList::iterator bdli = list.find(barNo); if (bdli != list.end()) { BarData::SizeData &bd(bdli->second.sizeData); NOTATION_DEBUG << "Changing width from " << bd.reconciledWidth << " to " << maxWidth << endl; double diff = maxWidth - bd.reconciledWidth; if (diff < -0.1 || diff > 0.1) { NOTATION_DEBUG << "(So needsLayout becomes true)" << endl; bdli->second.layoutData.needsLayout = true; } bd.reconciledWidth = maxWidth; } } ++barNo; } NOTATION_DEBUG << "Setting bar position for bar " << barNo << " to " << m_totalWidth << endl; m_barPositions[barNo] = m_totalWidth;}voidNotationHLayout::reconcileBarsPage(){ Profiler profiler("NotationHLayout::reconcileBarsPage"); int barNo = getFirstVisibleBar(); int barNoThisRow = 0; // pair of the recommended number of bars with those bars' // original total width, for each row std::vector<std::pair<int, double> > rowData; double stretchFactor = 10.0; double maxStaffNameWidth = 0.0; for (StaffIntMap::iterator i = m_staffNameWidths.begin(); i != m_staffNameWidths.end(); ++i) { if (i->second > maxStaffNameWidth) { maxStaffNameWidth = double(i->second); } } double pageWidthSoFar = maxStaffNameWidth; m_totalWidth = maxStaffNameWidth + getPreBarMargin(); NOTATION_DEBUG << "NotationHLayout::reconcileBarsPage: pageWidthSoFar is " << pageWidthSoFar << endl; for (;;) { Staff *widest = getStaffWithWidestBar(barNo); double maxWidth = m_spacing / 3; if (!widest) { // have we reached the end of the piece? if (barNo >= getLastVisibleBar()) break; // yes } else { maxWidth = m_barData[widest].find(barNo)->second.sizeData.idealWidth; } // Work on the assumption that this bar is the last in the // row. How would that make things look? double nextPageWidth = pageWidthSoFar + maxWidth; double nextStretchFactor = m_pageWidth / nextPageWidth; NOTATION_DEBUG << "barNo is " << barNo << ", maxWidth " << maxWidth << ", nextPageWidth " << nextPageWidth << ", nextStretchFactor " << nextStretchFactor << ", m_pageWidth " << m_pageWidth << endl; // We have to have at least one bar per row bool tooFar = false; if (barNoThisRow >= 1) { // If this stretch factor is "worse" than the previous // one, we've come too far and have too many bars if (fabs(1.0 - nextStretchFactor) > fabs(1.0 - stretchFactor)) { tooFar = true; } // If the next stretch factor is less than 1 and would // make this bar on any of the staffs narrower than it can // afford to be, then we've got too many bars //!!! rework this -- we have no concept of "too narrow" // any more but we can declare we don't want it any // narrower than e.g. 90% or something based on the spacing /*!!! if (!tooFar && (nextStretchFactor < 1.0)) { for (BarDataMap::iterator i = m_barData.begin(); i != m_barData.end(); ++i) { BarDataList &list = i->second; BarDataList::iterator bdli = list.find(barNo); if (bdli != list.end()) { BarData::SizeData &bd(bdli->second.sizeData); if ((nextStretchFactor * bd.idealWidth) < (double)(bd.fixedWidth + bd.baseWidth)) { tooFar = true; break; } } } } */ } if (tooFar) { rowData.push_back(std::pair<int, double>(barNoThisRow, pageWidthSoFar)); barNoThisRow = 1; // When we start a new row, we always need to allow for the // repeated clef and key at the start of it. int maxClefKeyWidth = getMaxRepeatedClefAndKeyWidth(barNo); for (BarDataMap::iterator i = m_barData.begin(); i != m_barData.end(); ++i) { BarDataList &list = i->second; BarDataList::iterator bdli = list.find(barNo); if (bdli != list.end()) { bdli->second.sizeData.clefKeyWidth = maxClefKeyWidth; } } pageWidthSoFar = maxWidth + maxClefKeyWidth; stretchFactor = m_pageWidth / pageWidthSoFar; } else { ++barNoThisRow; pageWidthSoFar = nextPageWidth; stretchFactor = nextStretchFactor; } ++barNo; } if (barNoThisRow > 0) { rowData.push_back(std::pair<int, double>(barNoThisRow, pageWidthSoFar)); } // Now we need to actually apply the widths barNo = getFirstVisibleBar(); for (unsigned int row = 0; row < rowData.size(); ++row) { barNoThisRow = barNo; int finalBarThisRow = barNo + rowData[row].first - 1; pageWidthSoFar = (row > 0 ? 0 : maxStaffNameWidth + getPreBarMargin()); stretchFactor = m_pageWidth / rowData[row].second; for (; barNoThisRow <= finalBarThisRow; ++barNoThisRow, ++barNo) { bool finalRow = (row == rowData.size() - 1); Staff *widest = getStaffWithWidestBar(barNo); if (finalRow && (stretchFactor > 1.0)) stretchFactor = 1.0; double maxWidth = 0.0; if (!widest) { // have we reached the end of the piece? (shouldn't happen) if (barNo >= getLastVisibleBar()) break; // yes else maxWidth = stretchFactor * (m_spacing / 3); } else { BarData &bd = m_barData[widest].find(barNo)->second; maxWidth = (stretchFactor * bd.sizeData.idealWidth) + bd.sizeData.clefKeyWidth; NOTATION_DEBUG << "setting maxWidth to " << (stretchFactor * bd.sizeData.idealWidth) << " + " << bd.sizeData.clefKeyWidth << " = " << maxWidth << endl; } if (barNoThisRow == finalBarThisRow) { if (!finalRow || (maxWidth > (m_pageWidth - pageWidthSoFar))) { maxWidth = m_pageWidth - pageWidthSoFar; NOTATION_DEBUG << "reset maxWidth to " << m_pageWidth << " - " << pageWidthSoFar << " = " << maxWidth << endl; } } m_barPositions[barNo] = m_totalWidth; m_totalWidth += maxWidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -