📄 notepixmapfactory.cpp
字号:
if (params.m_onLine) { m_above = std::max(m_above, dot.getHeight() / 2); } if (params.m_shifted) { if (params.m_stemGoesUp) { m_right += m_noteBodyWidth; } else { m_left = std::max(m_left, m_noteBodyWidth); } } if (params.m_tied) { m_right = std::max(m_right, params.m_tieLength); if (params.m_stemGoesUp) { m_below = std::max(m_below, m_noteBodyHeight * 2); } else { m_above = std::max(m_above, m_noteBodyHeight * 2); } } QPoint startPoint, endPoint; if (isStemmed && params.m_drawStem) { makeRoomForStemAndFlags(drawFlag ? flagCount : 0, stemLength, params, startPoint, endPoint); } if (isStemmed && params.m_drawStem && params.m_beamed) { makeRoomForBeams(params); } // for all other calculations we use the nominal note-body height // (same as the gap between staff lines), but here we want to know // if the pixmap itself is taller than that /*!!! int actualNoteBodyHeight = m_font->getHeight (m_style->getNoteHeadCharName(params.m_noteType).first); // - 2*m_origin.y(); if (actualNoteBodyHeight > m_noteBodyHeight) { m_below = std::max(m_below, actualNoteBodyHeight - m_noteBodyHeight); } */ if (painter) { painter->save(); m_p->beginExternal(painter); // NOTATION_DEBUG << "Translate: (" << x << "," << y << ")" << endl; painter->translate(x - m_left, y - m_above - m_noteBodyHeight / 2); } else { createPixmapAndMask(m_noteBodyWidth + m_left + m_right, m_noteBodyHeight + m_above + m_below); } if (params.m_tupletCount > 0) { drawTuplingLine(params); } if (isStemmed && params.m_drawStem && drawFlag) { drawFlags(flagCount, params, startPoint, endPoint); } if (params.m_accidental != NoAccidental) { drawAccidental(params.m_accidental, params.m_cautionary); } NoteStyle::CharNameRec charNameRec (m_style->getNoteHeadCharName(params.m_noteType)); CharName charName = charNameRec.first; bool inverted = charNameRec.second; NoteCharacter body = getCharacter (charName, params.m_highlighted ? HighlightedColour : params.m_quantized ? QuantizedColour : params.m_trigger ? TriggerColour : params.m_inRange ? PlainColour : OutRangeColour, inverted); QPoint bodyLocation(m_left - m_borderX, m_above - m_borderY + getStaffLineThickness() / 2); if (params.m_shifted) { if (params.m_stemGoesUp) { bodyLocation.rx() += m_noteBodyWidth; } else { bodyLocation.rx() -= m_noteBodyWidth - 1; } } m_p->drawNoteCharacter(bodyLocation.x(), bodyLocation.y(), body); if (params.m_dots > 0) { int x = m_left + m_noteBodyWidth + dotWidth / 2; int y = m_above + m_noteBodyHeight / 2 - dot.getHeight() / 2; if (params.m_onLine) y -= m_noteBodyHeight / 2; if (params.m_shifted) x += m_noteBodyWidth; else if (params.m_dotShifted) x += m_noteBodyWidth; for (int i = 0; i < params.m_dots; ++i) { m_p->drawNoteCharacter(x, y, dot); x += dotWidth; } } if (isStemmed && params.m_drawStem) { if (flagCount > 0 && !drawFlag && params.m_beamed) { drawBeams(endPoint, params, flagCount); } if (slashCount > 0) { drawSlashes(startPoint, params, slashCount); } if (m_selected) m_p->painter().setPen(GUIPalette::getColour(GUIPalette::SelectedElement)); else m_p->painter().setPen(Qt::black); // If we draw stems after beams, instead of beams after stems, // beam anti-aliasing won't damage stems but we have to shorten the // stems slightly first so that the stems don't extend all the way // through the beam into the anti-aliased region on the // other side of the beam that faces away from the note-heads. int shortening; if (flagCount > 0 && !drawFlag && params.m_beamed) shortening = 2; else shortening = 0; drawStem(params, startPoint, endPoint, shortening); } if (params.m_marks.size() > 0) { drawMarks(isStemmed, params, stemLength); } if (params.m_legerLines != 0) { drawLegerLines(params); } if (params.m_tied) { drawTie(!params.m_stemGoesUp, params.m_tieLength, dotWidth * params.m_dots); } if (painter) { painter->restore(); }}QCanvasPixmap*NotePixmapFactory::makeNoteHaloPixmap(const NotePixmapParameters ¶ms){ int nbh0 = getNoteBodyHeight(); int nbh = getNoteBodyHeight(params.m_noteType); int nbw0 = getNoteBodyHeight(); int nbw = getNoteBodyWidth(params.m_noteType); int hOffset = 0; createPixmapAndMask(nbw + nbw0, nbh + nbh0); drawNoteHalo(0, 0, nbw + nbw0, nbh + nbh0); return makeCanvasPixmap(QPoint(nbw0 / 2, nbh0));}voidNotePixmapFactory::drawNoteHalo(int x, int y, int w, int h) { m_p->painter().setPen(QPen(QColor(GUIPalette::CollisionHaloHue, GUIPalette::CollisionHaloSaturation, 255, QColor::Hsv), 1)); m_p->painter().setBrush(QColor(GUIPalette::CollisionHaloHue, GUIPalette::CollisionHaloSaturation, 255, QColor::Hsv)); m_p->drawEllipse(x, y, w, h);}intNotePixmapFactory::getStemLength(const NotePixmapParameters ¶ms) const{ if (params.m_beamed && params.m_stemLength >= 0) { return params.m_stemLength; } int stemLength = getStemLength(); int flagCount = m_style->getFlagCount(params.m_noteType); int slashCount = params.m_slashes; bool stemUp = params.m_stemGoesUp; int nbh = m_noteBodyHeight; if (flagCount > 2) { stemLength += getLineSpacing() * (flagCount - 2); } int width = 0, height = 0; if (flagCount > 0) { if (!stemUp) stemLength += nbh / 2; if (m_font->getDimensions(m_style->getFlagCharName(flagCount), width, height)) { stemLength = std::max(stemLength, height); } else if (m_font->getDimensions(m_style->getPartialFlagCharName(true), width, height) || m_font->getDimensions(m_style->getPartialFlagCharName(false), width, height)) { unsigned int flagSpace = m_noteBodyHeight; (void)m_font->getFlagSpacing(flagSpace); stemLength = std::max(stemLength, height + (flagCount - 1) * (int)flagSpace); } } if (slashCount > 3 && flagCount < 3) { stemLength += (slashCount - 3) * (nbh / 2); } if (params.m_stemLength >= 0) { if (flagCount == 0) return params.m_stemLength; stemLength = std::max(stemLength, params.m_stemLength); } return stemLength;}voidNotePixmapFactory::makeRoomForAccidental(Accidental a, bool cautionary, int shift, bool extra){ // General observation: where we're only using a character to // determine its dimensions, we should (for the moment) just // request it in screen mode, because it may be quicker and we // don't need to render it, and the dimensions are the same. NoteCharacter ac (m_font->getCharacter(m_style->getAccidentalCharName(a))); QPoint ah(m_font->getHotspot(m_style->getAccidentalCharName(a))); m_left += ac.getWidth() + (m_noteBodyWidth / 4 - m_borderX); if (shift > 0) { if (extra) { // The extra flag indicates that the first shift is to get // out of the way of a note head, thus has to move // possibly further, or at least a different amount. So // replace the first shift with a different one. --shift; m_left += m_noteBodyWidth - m_noteBodyWidth / 5; } if (shift > 0) { // The amount we shift for each accidental is the greater // of the probable shift for that accidental and the // probable shift for a sharp, on the assumption (usually // true in classical notation) that the sharp is the // widest accidental and that we may have other // accidentals possibly including sharps on other notes in // this chord that we can't know about here. int step = ac.getWidth() - ah.x(); if (a != Accidentals::Sharp) { NoteCharacter acSharp (m_font->getCharacter(m_style->getAccidentalCharName (Accidentals::Sharp))); QPoint ahSharp (m_font->getHotspot(m_style->getAccidentalCharName (Accidentals::Sharp))); step = std::max(step, acSharp.getWidth() - ahSharp.x()); } m_left += shift * step; } } if (cautionary) m_left += m_noteBodyWidth; int above = ah.y() - m_noteBodyHeight / 2; int below = (ac.getHeight() - ah.y()) - (m_noteBodyHeight - m_noteBodyHeight / 2); // subtract in case it's odd if (above > 0) m_above = std::max(m_above, above); if (below > 0) m_below = std::max(m_below, below);}voidNotePixmapFactory::drawAccidental(Accidental a, bool cautionary){ NoteCharacter ac = getCharacter (m_style->getAccidentalCharName(a), PlainColour, false); QPoint ah(m_font->getHotspot(m_style->getAccidentalCharName(a))); int ax = 0; if (cautionary) { ax += m_noteBodyWidth / 2; int bl = ac.getHeight() * 2 / 3; int by = m_above + m_noteBodyHeight / 2 - bl / 2; drawBracket(bl, true, false, m_noteBodyWidth*3 / 8, by); drawBracket(bl, false, false, ac.getWidth() + m_noteBodyWidth*5 / 8, by); } m_p->drawNoteCharacter(ax, m_above + m_noteBodyHeight / 2 - ah.y(), ac);}voidNotePixmapFactory::makeRoomForMarks(bool isStemmed, const NotePixmapParameters ¶ms, int stemLength){ int height = 0, width = 0; int gap = m_noteBodyHeight / 5 + 1; std::vector<Mark> normalMarks = params.getNormalMarks(); std::vector<Mark> aboveMarks = params.getAboveMarks(); for (std::vector<Mark>::iterator i = normalMarks.begin(); i != normalMarks.end(); ++i) { if (!Marks::isTextMark(*i)) { NoteCharacter character(m_font->getCharacter(m_style->getMarkCharName(*i))); height += character.getHeight() + gap; if (character.getWidth() > width) width = character.getWidth(); } else { // Inefficient to do this here _and_ in drawMarks, but // text marks are not all that common QString text = strtoqstr(Marks::getTextFromMark(*i)); QRect bounds = m_textMarkFontMetrics.boundingRect(text); height += bounds.height() + gap; if (bounds.width() > width) width = bounds.width(); } } if (height > 0) { if (isStemmed && params.m_stemGoesUp) { m_below += height + 1; } else { m_above += height + 1; } } height = 0; if (params.m_safeVertDistance > 0 && !aboveMarks.empty()) { m_above = std::max(m_above, params.m_safeVertDistance); } for (std::vector<Mark>::iterator i = aboveMarks.begin(); i != aboveMarks.end(); ++i) { if (!Marks::isFingeringMark(*i)) { Mark m(*i); if (m == Marks::TrillLine) m = Marks::LongTrill; if (m == Marks::LongTrill) { m_right = std::max(m_right, params.m_width); } NoteCharacter character(m_font->getCharacter(m_style->getMarkCharName(m))); height += character.getHeight() + gap; if (character.getWidth() > width) width = character.getWidth(); } else { // Inefficient to do this here _and_ in drawMarks QString text = strtoqstr(Marks::getFingeringFromMark(*i)); QRect bounds = m_fingeringFontMetrics.boundingRect(text); height += bounds.height() + gap + 3; if (bounds.width() > width) width = bounds.width(); } } if (height > 0) { if (isStemmed && params.m_stemGoesUp && params.m_safeVertDistance == 0) { m_above += stemLength + height + 1; } else { m_above += height + 1; } } m_left = std::max(m_left, width / 2 - m_noteBodyWidth / 2); m_right = std::max(m_right, width / 2 - m_noteBodyWidth / 2);}voidNotePixmapFactory::drawMarks(bool isStemmed, const NotePixmapParameters ¶ms, int stemLength){ int gap = m_noteBodyHeight / 5 + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -