LCOV - code coverage report
Current view: top level - src/engraving/rendering/single - singledraw.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 1570 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2023 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "singledraw.h"
      24              : 
      25              : #include "draw/painter.h"
      26              : #include "draw/svgrenderer.h"
      27              : #include "draw/types/drawtypes.h"
      28              : 
      29              : #include "iengravingconfiguration.h" // IWYU pragma: keep
      30              : 
      31              : #include "style/style.h"
      32              : #include "style/defaultstyle.h"
      33              : 
      34              : #include "dom/accidental.h"
      35              : #include "dom/actionicon.h"
      36              : #include "dom/ambitus.h"
      37              : #include "dom/arpeggio.h"
      38              : #include "dom/articulation.h"
      39              : 
      40              : #include "dom/bagpembell.h"
      41              : #include "dom/barline.h"
      42              : #include "dom/beam.h"
      43              : #include "dom/bend.h"
      44              : #include "dom/bracket.h"
      45              : #include "dom/breath.h"
      46              : 
      47              : #include "dom/chordbracket.h"
      48              : #include "dom/chordline.h"
      49              : #include "dom/clef.h"
      50              : #include "dom/capo.h"
      51              : 
      52              : #include "dom/deadslapped.h"
      53              : #include "dom/dynamic.h"
      54              : 
      55              : #include "dom/expression.h"
      56              : 
      57              : #include "dom/fermata.h"
      58              : #include "dom/figuredbass.h"
      59              : #include "dom/fingering.h"
      60              : #include "dom/fret.h"
      61              : 
      62              : #include "dom/glissando.h"
      63              : #include "dom/gradualtempochange.h"
      64              : #include "dom/guitarbend.h"
      65              : 
      66              : #include "dom/hairpin.h"
      67              : #include "dom/hammeronpulloff.h"
      68              : #include "dom/harppedaldiagram.h"
      69              : #include "dom/harmonicmark.h"
      70              : #include "dom/harmony.h"
      71              : #include "dom/hook.h"
      72              : 
      73              : #include "dom/image.h"
      74              : #include "dom/instrchange.h"
      75              : #include "dom/instrumentname.h"
      76              : 
      77              : #include "dom/jump.h"
      78              : 
      79              : #include "dom/keysig.h"
      80              : 
      81              : #include "dom/layoutbreak.h"
      82              : #include "dom/ledgerline.h"
      83              : #include "dom/letring.h"
      84              : #include "dom/lyrics.h"
      85              : 
      86              : #include "dom/marker.h"
      87              : #include "dom/measure.h"
      88              : #include "dom/measurenumber.h"
      89              : #include "dom/measurerepeat.h"
      90              : 
      91              : #include "dom/note.h"
      92              : #include "dom/noteline.h"
      93              : 
      94              : #include "dom/ornament.h"
      95              : #include "dom/ottava.h"
      96              : 
      97              : #include "dom/palmmute.h"
      98              : #include "dom/part.h"
      99              : #include "dom/pedal.h"
     100              : #include "dom/pickscrape.h"
     101              : #include "dom/playcounttext.h"
     102              : #include "dom/playtechannotation.h"
     103              : 
     104              : #include "dom/rasgueado.h"
     105              : #include "dom/rehearsalmark.h"
     106              : #include "dom/rest.h"
     107              : 
     108              : #include "dom/score.h"
     109              : #include "dom/shadownote.h"
     110              : #include "dom/slur.h"
     111              : #include "dom/soundflag.h"
     112              : #include "dom/spacer.h"
     113              : #include "dom/staff.h"
     114              : #include "dom/stafflines.h"
     115              : #include "dom/staffstate.h"
     116              : #include "dom/stafftext.h"
     117              : #include "dom/stafftype.h"
     118              : #include "dom/stafftypechange.h"
     119              : #include "dom/stavesharinglabel.h"
     120              : #include "dom/stem.h"
     121              : #include "dom/stemslash.h"
     122              : #include "dom/sticking.h"
     123              : #include "dom/stringtunings.h"
     124              : #include "dom/symbol.h"
     125              : #include "dom/systemdivider.h"
     126              : #include "dom/systemtext.h"
     127              : 
     128              : #include "dom/tapping.h"
     129              : #include "dom/tempotext.h"
     130              : #include "dom/text.h"
     131              : #include "dom/textbase.h"
     132              : #include "dom/textline.h"
     133              : #include "dom/textlinebase.h"
     134              : #include "dom/tie.h"
     135              : #include "dom/timesig.h"
     136              : #include "dom/tremolosinglechord.h"
     137              : #include "dom/tremolotwochord.h"
     138              : #include "dom/tremolobar.h"
     139              : #include "dom/trill.h"
     140              : #include "dom/tripletfeel.h"
     141              : #include "dom/tuplet.h"
     142              : 
     143              : #include "dom/vibrato.h"
     144              : #include "dom/volta.h"
     145              : 
     146              : #include "dom/whammybar.h"
     147              : 
     148              : #include "editing/mscoreview.h"
     149              : 
     150              : #include "rendering/score/stemlayout.h"
     151              : 
     152              : #include "infrastructure/rtti.h"
     153              : 
     154              : using namespace mu::engraving::rendering::single;
     155              : using namespace mu::engraving;
     156              : using namespace mu::engraving::rtti;
     157              : using namespace muse;
     158              : using namespace muse::draw;
     159              : 
     160            0 : void SingleDraw::drawItem(const EngravingItem* item, Painter* painter, const PaintOptions& opt)
     161              : {
     162            0 :     switch (item->type()) {
     163            0 :     case ElementType::ACCIDENTAL:   draw(item_cast<const Accidental*>(item), painter, opt);
     164            0 :         break;
     165            0 :     case ElementType::ACTION_ICON:  draw(item_cast<const ActionIcon*>(item), painter, opt);
     166            0 :         break;
     167            0 :     case ElementType::AMBITUS:      draw(item_cast<const Ambitus*>(item), painter, opt);
     168            0 :         break;
     169            0 :     case ElementType::ARPEGGIO:     draw(item_cast<const Arpeggio*>(item), painter, opt);
     170            0 :         break;
     171            0 :     case ElementType::CHORD_BRACKET: draw(item_cast<const ChordBracket*>(item), painter, opt);
     172            0 :         break;
     173            0 :     case ElementType::ARTICULATION: draw(item_cast<const Articulation*>(item), painter, opt);
     174            0 :         break;
     175              : 
     176            0 :     case ElementType::BAGPIPE_EMBELLISHMENT: draw(item_cast<const BagpipeEmbellishment*>(item), painter, opt);
     177            0 :         break;
     178            0 :     case ElementType::BAR_LINE:     draw(item_cast<const BarLine*>(item), painter, opt);
     179            0 :         break;
     180            0 :     case ElementType::BEAM:         draw(item_cast<const Beam*>(item), painter, opt);
     181            0 :         break;
     182            0 :     case ElementType::BEND:         draw(item_cast<const Bend*>(item), painter, opt);
     183            0 :         break;
     184            0 :     case ElementType::BRACKET:      draw(item_cast<const Bracket*>(item), painter, opt);
     185            0 :         break;
     186            0 :     case ElementType::BREATH:       draw(item_cast<const Breath*>(item), painter, opt);
     187            0 :         break;
     188              : 
     189            0 :     case ElementType::CHORDLINE:    draw(item_cast<const ChordLine*>(item), painter, opt);
     190            0 :         break;
     191            0 :     case ElementType::CLEF:         draw(item_cast<const Clef*>(item), painter, opt);
     192            0 :         break;
     193            0 :     case ElementType::CAPO:         draw(item_cast<const Capo*>(item), painter, opt);
     194            0 :         break;
     195              : 
     196            0 :     case ElementType::DEAD_SLAPPED: draw(item_cast<const DeadSlapped*>(item), painter, opt);
     197            0 :         break;
     198            0 :     case ElementType::DYNAMIC:      draw(item_cast<const Dynamic*>(item), painter, opt);
     199            0 :         break;
     200              : 
     201            0 :     case ElementType::EXPRESSION:   draw(item_cast<const Expression*>(item), painter, opt);
     202            0 :         break;
     203              : 
     204            0 :     case ElementType::FERMATA:      draw(item_cast<const Fermata*>(item), painter, opt);
     205            0 :         break;
     206            0 :     case ElementType::FIGURED_BASS: draw(item_cast<const FiguredBass*>(item), painter, opt);
     207            0 :         break;
     208            0 :     case ElementType::FINGERING:    draw(item_cast<const Fingering*>(item), painter, opt);
     209            0 :         break;
     210            0 :     case ElementType::FRET_DIAGRAM: draw(item_cast<const FretDiagram*>(item), painter, opt);
     211            0 :         break;
     212            0 :     case ElementType::FSYMBOL:      draw(item_cast<const FSymbol*>(item), painter, opt);
     213            0 :         break;
     214              : 
     215            0 :     case ElementType::GLISSANDO_SEGMENT: draw(item_cast<const GlissandoSegment*>(item), painter, opt);
     216            0 :         break;
     217            0 :     case ElementType::GRADUAL_TEMPO_CHANGE_SEGMENT: draw(item_cast<const GradualTempoChangeSegment*>(item), painter, opt);
     218            0 :         break;
     219            0 :     case ElementType::GUITAR_BEND_SEGMENT: draw(item_cast<const GuitarBendSegment*>(item), painter, opt);
     220            0 :         break;
     221            0 :     case ElementType::GUITAR_BEND_TEXT: drawTextBase(toTextBase(item), painter, opt);
     222            0 :         break;
     223              : 
     224            0 :     case ElementType::HAIRPIN_SEGMENT: draw(item_cast<const HairpinSegment*>(item), painter, opt);
     225            0 :         break;
     226            0 :     case ElementType::HAMMER_ON_PULL_OFF_SEGMENT: draw(item_cast<const HammerOnPullOffSegment*>(item), painter, opt);
     227            0 :         break;
     228            0 :     case ElementType::HAMMER_ON_PULL_OFF_TEXT: draw(item_cast<const HammerOnPullOffText*>(item), painter, opt);
     229            0 :         break;
     230            0 :     case ElementType::HARP_DIAGRAM: draw(item_cast<const HarpPedalDiagram*>(item), painter, opt);
     231            0 :         break;
     232            0 :     case ElementType::HARMONIC_MARK_SEGMENT: draw(item_cast<const HarmonicMarkSegment*>(item), painter, opt);
     233            0 :         break;
     234            0 :     case ElementType::HARMONY:      draw(item_cast<const Harmony*>(item), painter, opt);
     235            0 :         break;
     236            0 :     case ElementType::HOOK:         draw(item_cast<const Hook*>(item), painter, opt);
     237            0 :         break;
     238              : 
     239            0 :     case ElementType::IMAGE:        draw(item_cast<const Image*>(item), painter, opt);
     240            0 :         break;
     241            0 :     case ElementType::INSTRUMENT_CHANGE: draw(item_cast<const InstrumentChange*>(item), painter, opt);
     242            0 :         break;
     243            0 :     case ElementType::INSTRUMENT_NAME: draw(item_cast<const InstrumentName*>(item), painter, opt);
     244            0 :         break;
     245              : 
     246            0 :     case ElementType::JUMP:         draw(item_cast<const Jump*>(item), painter, opt);
     247            0 :         break;
     248              : 
     249            0 :     case ElementType::KEYSIG:       draw(item_cast<const KeySig*>(item), painter, opt);
     250            0 :         break;
     251              : 
     252            0 :     case ElementType::LAYOUT_BREAK: draw(item_cast<const LayoutBreak*>(item), painter, opt);
     253            0 :         break;
     254            0 :     case ElementType::LEDGER_LINE:  draw(item_cast<const LedgerLine*>(item), painter, opt);
     255            0 :         break;
     256            0 :     case ElementType::LET_RING_SEGMENT:     draw(item_cast<const LetRingSegment*>(item), painter, opt);
     257            0 :         break;
     258            0 :     case ElementType::LYRICS:       draw(item_cast<const Lyrics*>(item), painter, opt);
     259            0 :         break;
     260              : 
     261            0 :     case ElementType::MARKER:               draw(item_cast<const Marker*>(item), painter, opt);
     262            0 :         break;
     263            0 :     case ElementType::MEASURE_NUMBER:       draw(item_cast<const MeasureNumber*>(item), painter, opt);
     264            0 :         break;
     265            0 :     case ElementType::MEASURE_REPEAT:       draw(item_cast<const MeasureRepeat*>(item), painter, opt);
     266            0 :         break;
     267              : 
     268            0 :     case ElementType::NOTE:                 draw(item_cast<const Note*>(item), painter, opt);
     269            0 :         break;
     270            0 :     case ElementType::NOTEHEAD:             draw(item_cast<const NoteHead*>(item), painter, opt);
     271            0 :         break;
     272            0 :     case ElementType::NOTELINE_SEGMENT:     draw(item_cast<const NoteLineSegment*>(item), painter, opt);
     273            0 :         break;
     274              : 
     275            0 :     case ElementType::ORNAMENT:             draw(item_cast<const Ornament*>(item), painter, opt);
     276            0 :         break;
     277            0 :     case ElementType::OTTAVA_SEGMENT:       draw(item_cast<const OttavaSegment*>(item), painter, opt);
     278            0 :         break;
     279              : 
     280            0 :     case ElementType::PALM_MUTE_SEGMENT:    draw(item_cast<const PalmMuteSegment*>(item), painter, opt);
     281            0 :         break;
     282            0 :     case ElementType::PEDAL_SEGMENT:        draw(item_cast<const PedalSegment*>(item), painter, opt);
     283            0 :         break;
     284            0 :     case ElementType::PICK_SCRAPE_SEGMENT:  draw(item_cast<const PickScrapeSegment*>(item), painter, opt);
     285            0 :         break;
     286            0 :     case ElementType::PLAY_COUNT_TEXT:      draw(item_cast<const PlayCountText*>(item), painter, opt);
     287            0 :         break;
     288            0 :     case ElementType::PLAYTECH_ANNOTATION:  draw(item_cast<const PlayTechAnnotation*>(item), painter, opt);
     289            0 :         break;
     290              : 
     291            0 :     case ElementType::RASGUEADO_SEGMENT:    draw(item_cast<const RasgueadoSegment*>(item), painter, opt);
     292            0 :         break;
     293            0 :     case ElementType::REHEARSAL_MARK:       draw(item_cast<const RehearsalMark*>(item), painter, opt);
     294            0 :         break;
     295            0 :     case ElementType::REST:                 draw(item_cast<const Rest*>(item), painter, opt);
     296            0 :         break;
     297              : 
     298            0 :     case ElementType::SHADOW_NOTE:          draw(item_cast<const ShadowNote*>(item), painter, opt);
     299            0 :         break;
     300            0 :     case ElementType::SLUR_SEGMENT:         draw(item_cast<const SlurSegment*>(item), painter, opt);
     301            0 :         break;
     302            0 :     case ElementType::SPACER:               draw(item_cast<const Spacer*>(item), painter, opt);
     303            0 :         break;
     304            0 :     case ElementType::STAFF_LINES:          draw(item_cast<const StaffLines*>(item), painter, opt);
     305            0 :         break;
     306            0 :     case ElementType::STAFF_STATE:          draw(item_cast<const StaffState*>(item), painter, opt);
     307            0 :         break;
     308            0 :     case ElementType::STAFF_TEXT:           draw(item_cast<const StaffText*>(item), painter, opt);
     309            0 :         break;
     310            0 :     case ElementType::STAVE_SHARING_LABEL:  draw(item_cast<const StaveSharingLabel*>(item), painter, opt);
     311            0 :         break;
     312            0 :     case ElementType::STAFFTYPE_CHANGE:     draw(item_cast<const StaffTypeChange*>(item), painter, opt);
     313            0 :         break;
     314            0 :     case ElementType::STEM:                 draw(item_cast<const Stem*>(item), painter, opt);
     315            0 :         break;
     316            0 :     case ElementType::STEM_SLASH:           draw(item_cast<const StemSlash*>(item), painter, opt);
     317            0 :         break;
     318            0 :     case ElementType::STICKING:             draw(item_cast<const Sticking*>(item), painter, opt);
     319            0 :         break;
     320            0 :     case ElementType::STRING_TUNINGS:       draw(item_cast<const StringTunings*>(item), painter, opt);
     321            0 :         break;
     322            0 :     case ElementType::SYMBOL:               draw(item_cast<const Symbol*>(item), painter, opt);
     323            0 :         break;
     324            0 :     case ElementType::SYSTEM_DIVIDER:       draw(item_cast<const SystemDivider*>(item), painter, opt);
     325            0 :         break;
     326            0 :     case ElementType::SYSTEM_TEXT:          draw(item_cast<const SystemText*>(item), painter, opt);
     327            0 :         break;
     328            0 :     case ElementType::SOUND_FLAG:           draw(item_cast<const SoundFlag*>(item), painter, opt);
     329            0 :         break;
     330              : 
     331            0 :     case ElementType::TAPPING:              draw(item_cast<const Tapping*>(item), painter, opt);
     332            0 :         break;
     333            0 :     case ElementType::TEMPO_TEXT:           draw(item_cast<const TempoText*>(item), painter, opt);
     334            0 :         break;
     335            0 :     case ElementType::TEXT:                 draw(item_cast<const Text*>(item), painter, opt);
     336            0 :         break;
     337            0 :     case ElementType::TEXTLINE_SEGMENT:     draw(item_cast<const TextLineSegment*>(item), painter, opt);
     338            0 :         break;
     339            0 :     case ElementType::TIE_SEGMENT:          draw(item_cast<const TieSegment*>(item), painter, opt);
     340            0 :         break;
     341            0 :     case ElementType::TIMESIG:              draw(item_cast<const TimeSig*>(item), painter, opt);
     342            0 :         break;
     343            0 :     case ElementType::TREMOLO_SINGLECHORD:  draw(item_cast<const TremoloSingleChord*>(item), painter, opt);
     344            0 :         break;
     345            0 :     case ElementType::TREMOLO_TWOCHORD:     draw(item_cast<const TremoloTwoChord*>(item), painter, opt);
     346            0 :         break;
     347            0 :     case ElementType::TREMOLOBAR:           draw(item_cast<const TremoloBar*>(item), painter, opt);
     348            0 :         break;
     349            0 :     case ElementType::TRILL_SEGMENT:        draw(item_cast<const TrillSegment*>(item), painter, opt);
     350            0 :         break;
     351            0 :     case ElementType::TRIPLET_FEEL:         draw(item_cast<const TripletFeel*>(item), painter, opt);
     352            0 :         break;
     353            0 :     case ElementType::TUPLET:               draw(item_cast<const Tuplet*>(item), painter, opt);
     354            0 :         break;
     355              : 
     356            0 :     case ElementType::VIBRATO_SEGMENT:      draw(item_cast<const VibratoSegment*>(item), painter, opt);
     357            0 :         break;
     358            0 :     case ElementType::VOLTA_SEGMENT:        draw(item_cast<const VoltaSegment*>(item), painter, opt);
     359            0 :         break;
     360              : 
     361            0 :     case ElementType::WHAMMY_BAR_SEGMENT:   draw(item_cast<const WhammyBarSegment*>(item), painter, opt);
     362            0 :         break;
     363            0 :     default:
     364            0 :         NOT_IMPLEMENTED << item->typeName();
     365            0 :         UNREACHABLE;
     366              :     }
     367            0 : }
     368              : 
     369            0 : void SingleDraw::draw(const Accidental* item, Painter* painter, const PaintOptions& opt)
     370              : {
     371            0 :     IF_ASSERT_FAILED(item->ldata()) {
     372            0 :         return;
     373              :     }
     374              : 
     375            0 :     painter->setPen(item->curColor(opt));
     376            0 :     for (const Accidental::LayoutData::Sym& e : item->ldata()->syms) {
     377            0 :         item->drawSymbol(e.sym, painter, PointF(e.x, e.y));
     378              :     }
     379              : }
     380              : 
     381            0 : void SingleDraw::draw(const ActionIcon* item, Painter* painter, const PaintOptions&)
     382              : {
     383              :     TRACE_DRAW_ITEM;
     384            0 :     painter->setFont(item->iconFont());
     385            0 :     painter->drawText(PointF(), Char(item->icon()));
     386            0 : }
     387              : 
     388            0 : void SingleDraw::draw(const Ambitus* item, Painter* painter, const PaintOptions& opt)
     389              : {
     390              :     TRACE_DRAW_ITEM;
     391              : 
     392            0 :     const Ambitus::LayoutData* layoutData = item->ldata();
     393            0 :     IF_ASSERT_FAILED(layoutData) {
     394            0 :         return;
     395              :     }
     396              : 
     397            0 :     double spatium = item->spatium();
     398            0 :     double lw = item->lineWidth().val() * spatium;
     399            0 :     painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     400              : 
     401            0 :     item->drawSymbol(item->noteHead(), painter, layoutData->topPos);
     402            0 :     item->drawSymbol(item->noteHead(), painter, layoutData->bottomPos);
     403            0 :     if (item->hasLine()) {
     404            0 :         painter->drawLine(layoutData->line);
     405              :     }
     406              : }
     407              : 
     408            0 : void SingleDraw::draw(const Arpeggio* item, Painter* painter, const PaintOptions& opt)
     409              : {
     410              :     TRACE_DRAW_ITEM;
     411              : 
     412            0 :     const Arpeggio::LayoutData* ldata = item->ldata();
     413            0 :     IF_ASSERT_FAILED(ldata) {
     414            0 :         return;
     415              :     }
     416              : 
     417            0 :     const double y1 = ldata->bbox().top();
     418            0 :     const double y2 = ldata->bbox().bottom();
     419            0 :     const double lineWidth = item->style().styleAbsolute(Sid::arpeggioLineWidth);
     420              : 
     421            0 :     painter->setPen(Pen(item->curColor(opt), lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
     422            0 :     painter->save();
     423              : 
     424            0 :     switch (item->arpeggioType()) {
     425            0 :     case ArpeggioType::NORMAL:
     426              :     case ArpeggioType::UP:
     427              :     {
     428            0 :         const RectF& r = ldata->symsBBox;
     429            0 :         painter->rotate(-90.0);
     430            0 :         item->drawSymbols(ldata->symbols, painter, PointF(-r.right() - y1, -r.bottom() + r.height()));
     431            0 :     } break;
     432              : 
     433            0 :     case ArpeggioType::DOWN:
     434              :     {
     435            0 :         const RectF& r = ldata->symsBBox;
     436            0 :         painter->rotate(90.0);
     437            0 :         item->drawSymbols(ldata->symbols, painter, PointF(-r.left() + y1, -r.top() - r.height()));
     438            0 :     } break;
     439              : 
     440            0 :     case ArpeggioType::UP_STRAIGHT:
     441              :     {
     442            0 :         const RectF& r = ldata->symsBBox;
     443            0 :         double x1 = item->spatium() * 0.5;
     444            0 :         item->drawSymbol(SymId::arrowheadBlackUp, painter, PointF(x1 - r.width() * 0.5, y1 - r.top()));
     445            0 :         double ny1 = y1 - r.top() * 0.5;
     446            0 :         painter->drawLine(LineF(x1, ny1, x1, y2));
     447            0 :     } break;
     448              : 
     449            0 :     case ArpeggioType::DOWN_STRAIGHT:
     450              :     {
     451            0 :         const RectF& r = ldata->symsBBox;
     452            0 :         double x1 = item->spatium() * 0.5;
     453            0 :         item->drawSymbol(SymId::arrowheadBlackDown, painter, PointF(x1 - r.width() * 0.5, y2 - r.bottom()));
     454            0 :         double ny2 = y2 + r.top() * 0.5;
     455            0 :         painter->drawLine(LineF(x1, y1, x1, ny2));
     456            0 :     } break;
     457              : 
     458            0 :     case ArpeggioType::BRACKET:
     459              :     {
     460            0 :         double w = item->style().styleS(Sid::arpeggioHookLen).val() * item->spatium();
     461            0 :         painter->drawLine(LineF(0.0, y1, w, y1));
     462            0 :         painter->drawLine(LineF(0.0, y2, w, y2));
     463            0 :         painter->drawLine(LineF(0.0, y1 - lineWidth / 2, 0.0, y2 + lineWidth / 2));
     464            0 :     } break;
     465              :     }
     466            0 :     painter->restore();
     467              : }
     468              : 
     469            0 : void SingleDraw::draw(const ChordBracket* item, muse::draw::Painter* painter, const PaintOptions& opt)
     470              : {
     471            0 :     const Arpeggio::LayoutData* ldata = item->ldata();
     472              : 
     473            0 :     const double lineWidth = item->style().styleAbsolute(Sid::chordBracketLineWidth);
     474            0 :     painter->setPen(Pen(item->curColor(opt), lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
     475              : 
     476            0 :     const double halfLineWidth = 0.5 * lineWidth;
     477            0 :     const double y1 = ldata->bbox().top() + halfLineWidth;
     478            0 :     const double y2 = ldata->bbox().bottom() - halfLineWidth;
     479              : 
     480            0 :     double w = item->absoluteFromSpatium(item->hookLength());
     481            0 :     if (item->hookPos() != DirectionV::DOWN) {
     482            0 :         painter->drawLine(LineF(0.0, y1, w, y1));
     483              :     }
     484            0 :     if (item->hookPos() != DirectionV::UP) {
     485            0 :         painter->drawLine(LineF(0.0, y2, w, y2));
     486              :     }
     487              : 
     488            0 :     const double x = halfLineWidth;
     489            0 :     painter->drawLine(LineF(x, y1, x, y2));
     490            0 : }
     491              : 
     492            0 : void SingleDraw::draw(const Articulation* item, Painter* painter, const PaintOptions& opt)
     493              : {
     494              :     TRACE_DRAW_ITEM;
     495              : 
     496            0 :     painter->setPen(item->curColor(opt));
     497              : 
     498            0 :     if (item->textType() == ArticulationTextType::NO_TEXT) {
     499            0 :         item->drawSymbol(item->symId(), painter, PointF(-0.5 * item->width(), 0.0));
     500              :     } else {
     501            0 :         item->text()->setColor(item->curColor(opt));
     502            0 :         drawTextBase(item->text(), painter, opt);
     503              :     }
     504            0 : }
     505              : 
     506            0 : void SingleDraw::draw(const Note* item, Painter* painter, const PaintOptions& opt)
     507              : {
     508              :     TRACE_DRAW_ITEM;
     509            0 :     if (item->hidden()) {
     510            0 :         return;
     511              :     }
     512              : 
     513            0 :     const Note::LayoutData* ldata = item->ldata();
     514            0 :     auto config = item->configuration();
     515              : 
     516            0 :     bool negativeFret = item->negativeFretUsed() && item->staff()->isTabStaff(item->tick());
     517              : 
     518            0 :     Color c(negativeFret && !opt.isPrinting ? config->criticalColor() : item->curColor(opt));
     519            0 :     painter->setPen(c);
     520            0 :     bool tablature = item->staff() && item->staff()->isTabStaff(item->chord()->tick());
     521              : 
     522              :     // tablature
     523            0 :     if (tablature) {
     524            0 :         if (item->displayFret() == Note::DisplayFretOption::Hide) {
     525            0 :             return;
     526              :         }
     527            0 :         const Staff* st = item->staff();
     528            0 :         const StaffType* tab = st->staffTypeForElement(item);
     529            0 :         if (item->tieBackNonPartial() && !tab->showBackTied()) {
     530            0 :             if (item->chord()->measure()->system() == item->tieBack()->startNote()->chord()->measure()->system() && item->el().empty()) {
     531              :                 // fret should be hidden, so return without drawing it
     532            0 :                 return;
     533              :             }
     534              :         }
     535              :         // draw background, if required (to hide a segment of string line or to show a fretting conflict)
     536            0 :         if (!tab->linesThrough() || item->fretConflict()) {
     537            0 :             double d  = item->spatium() * .1;
     538            0 :             RectF bb = RectF(ldata->bbox().x() - d,
     539            0 :                              tab->fretMaskY() * item->magS(),
     540            0 :                              ldata->bbox().width() + 2 * d,
     541            0 :                              tab->fretMaskH() * item->magS());
     542              :             // we do not know which viewer did this draw() call
     543              :             // so update all:
     544            0 :             if (!item->score()->getViewer().empty()) {
     545            0 :                 for (MuseScoreView* view : item->score()->getViewer()) {
     546            0 :                     view->drawBackground(painter, bb);
     547              :                 }
     548              :             } else {
     549            0 :                 painter->fillRect(bb, config->noteBackgroundColor());
     550              :             }
     551              : 
     552            0 :             if (item->fretConflict() && !opt.isPrinting && item->score()->showUnprintable()) {                //on fret conflict, draw on red background
     553            0 :                 painter->save();
     554            0 :                 painter->setPen(config->criticalColor());
     555            0 :                 painter->setBrush(config->criticalColor());
     556            0 :                 painter->drawRect(bb);
     557            0 :                 painter->restore();
     558              :             }
     559              :         }
     560            0 :         Font f(tab->fretFont());
     561            0 :         f.setPointSizeF(f.pointSizeF() * item->magS());
     562            0 :         painter->setFont(f);
     563            0 :         painter->setPen(c);
     564            0 :         double startPosX = ldata->bbox().x();
     565              : 
     566            0 :         painter->drawText(PointF(startPosX, tab->fretFontYOffset() * item->magS()), item->fretString());
     567            0 :     }
     568              :     // NOT tablature
     569              :     else {
     570              :         // skip drawing, if second note of a cross-measure value
     571            0 :         if (item->chord() && item->chord()->crossMeasure() == CrossMeasure::SECOND) {
     572            0 :             return;
     573              :         }
     574              :         // warn if pitch extends usable range of instrument
     575              :         // by coloring the notehead
     576            0 :         if (item->chord() && item->chord()->segment() && item->staff() && !opt.isPrinting
     577            0 :             && MScore::warnPitchRange && !item->staff()->isDrumStaff(item->chord()->tick())) {
     578            0 :             const Instrument* in = item->originPart()->instrument(item->chord()->tick());
     579            0 :             int i = item->ppitch();
     580            0 :             if (i < in->minPitchP() || i > in->maxPitchP()) {
     581            0 :                 painter->setPen(
     582            0 :                     item->selected() ? config->criticalSelectedColor() : config->criticalColor());
     583            0 :             } else if (i < in->minPitchA() || i > in->maxPitchA()) {
     584            0 :                 painter->setPen(item->selected() ? config->warningSelectedColor() : config->warningColor());
     585              :             }
     586              :         }
     587              :         // Warn if notes are unplayable based on previous harp diagram setting
     588            0 :         if (item->chord() && item->chord()->segment() && item->staff() && !opt.isPrinting
     589            0 :             && !item->staff()->isDrumStaff(item->chord()->tick())) {
     590            0 :             HarpPedalDiagram* prevDiagram = item->originPart()->currentHarpDiagram(item->chord()->segment()->tick());
     591            0 :             if (prevDiagram && !prevDiagram->isTpcPlayable(item->tpc())) {
     592            0 :                 painter->setPen(item->selected() ? config->criticalSelectedColor() : config->criticalColor());
     593              :             }
     594              :         }
     595              :         // draw blank notehead to avoid staff and ledger lines
     596            0 :         if (ldata->cachedSymNull() != SymId::noSym) {
     597            0 :             painter->save();
     598            0 :             painter->setPen(config->noteBackgroundColor());
     599            0 :             item->drawSymbol(ldata->cachedSymNull(), painter);
     600            0 :             painter->restore();
     601              :         }
     602            0 :         item->drawSymbol(ldata->cachedNoteheadSym.value(), painter);
     603              :     }
     604            0 : }
     605              : 
     606            0 : void SingleDraw::draw(const NoteHead* item, Painter* painter, const PaintOptions& opt)
     607              : {
     608            0 :     draw(static_cast<const Symbol*>(item), painter, opt);
     609            0 : }
     610              : 
     611            0 : void SingleDraw::draw(const NoteLineSegment*, Painter*, const PaintOptions&)
     612              : {
     613              :     // TRACE_DRAW_ITEM;
     614              :     // To be implemented
     615            0 : }
     616              : 
     617            0 : void SingleDraw::draw(const Ornament* item, Painter* painter, const PaintOptions& opt)
     618              : {
     619            0 :     draw(static_cast<const Articulation*>(item), painter, opt);
     620            0 : }
     621              : 
     622            0 : void SingleDraw::draw(const BagpipeEmbellishment* item, Painter* painter, const PaintOptions& opt)
     623              : {
     624              :     TRACE_DRAW_ITEM;
     625              : 
     626            0 :     const BagpipeEmbellishment::LayoutData* data = item->ldata();
     627            0 :     IF_ASSERT_FAILED(data) {
     628            0 :         return;
     629              :     }
     630            0 :     const BagpipeEmbellishment::LayoutData::BeamData& dataBeam = data->beamData;
     631              : 
     632            0 :     Pen pen(item->curColor(opt), data->stemLineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
     633            0 :     painter->setPen(pen);
     634              : 
     635              :     // draw the notes including stem, (optional) flag and (optional) ledger line
     636            0 :     for (const auto& p : data->notesData) {
     637            0 :         const BagpipeEmbellishment::LayoutData::NoteData& noteData = p.second;
     638              : 
     639              :         // Draw Grace Note
     640              :         {
     641              :             // draw head
     642            0 :             item->drawSymbol(data->headsym, painter, noteData.headXY);
     643              : 
     644              :             // draw stem
     645            0 :             painter->drawLine(noteData.stemLine);
     646              : 
     647            0 :             if (data->isDrawFlag) {
     648              :                 // draw flag
     649            0 :                 item->drawSymbol(data->flagsym, painter, noteData.flagXY);
     650              :             }
     651              :         }
     652              : 
     653              :         // draw the ledger line for high A
     654            0 :         if (!noteData.ledgerLine.isNull()) {
     655            0 :             painter->drawLine(noteData.ledgerLine);
     656              :         }
     657              :     }
     658              : 
     659            0 :     if (data->isDrawBeam) {
     660            0 :         Pen beamPen(item->curColor(opt), dataBeam.width, PenStyle::SolidLine, PenCapStyle::FlatCap);
     661            0 :         painter->setPen(beamPen);
     662              :         // draw the beams
     663            0 :         auto drawBeams = [](Painter* painter, const double spatium,
     664              :                             const double x1, const double x2, double y)
     665              :         {
     666              :             // draw the beams
     667            0 :             painter->drawLine(LineF(x1, y, x2, y));
     668            0 :             y += spatium / 1.5;
     669            0 :             painter->drawLine(LineF(x1, y, x2, y));
     670            0 :             y += spatium / 1.5;
     671            0 :             painter->drawLine(LineF(x1, y, x2, y));
     672            0 :         };
     673              : 
     674            0 :         drawBeams(painter, data->spatium, dataBeam.x1, dataBeam.x2, dataBeam.y);
     675            0 :     }
     676            0 : }
     677              : 
     678            0 : static void drawDots(const BarLine* item, Painter* painter, double x)
     679              : {
     680            0 :     double spatium = item->spatium();
     681              : 
     682            0 :     double y1l = 1.5 * spatium;
     683            0 :     double y2l = 2.5 * spatium;
     684              : 
     685            0 :     item->drawSymbol(SymId::repeatDot, painter, PointF(x, y1l));
     686            0 :     item->drawSymbol(SymId::repeatDot, painter, PointF(x, y2l));
     687            0 : }
     688              : 
     689            0 : static void drawTips(const BarLine* item, Painter* painter, bool reversed, double x)
     690              : {
     691            0 :     const BarLine::LayoutData* ldata = item->ldata();
     692            0 :     if (reversed) {
     693            0 :         if (item->isTop()) {
     694            0 :             item->drawSymbol(SymId::reversedBracketTop, painter, PointF(x - item->symWidth(SymId::reversedBracketTop), ldata->y1));
     695              :         }
     696            0 :         if (item->isBottom()) {
     697            0 :             item->drawSymbol(SymId::reversedBracketBottom, painter, PointF(x - item->symWidth(SymId::reversedBracketBottom), ldata->y2));
     698              :         }
     699              :     } else {
     700            0 :         if (item->isTop()) {
     701            0 :             item->drawSymbol(SymId::bracketTop, painter, PointF(x, ldata->y1));
     702              :         }
     703            0 :         if (item->isBottom()) {
     704            0 :             item->drawSymbol(SymId::bracketBottom, painter, PointF(x, ldata->y2));
     705              :         }
     706              :     }
     707            0 : }
     708              : 
     709            0 : void SingleDraw::draw(const BarLine* item, Painter* painter, const PaintOptions& opt)
     710              : {
     711              :     TRACE_DRAW_ITEM;
     712            0 :     const BarLine::LayoutData* ldata = item->ldata();
     713            0 :     switch (item->barLineType()) {
     714            0 :     case BarLineType::NORMAL: {
     715            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     716            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     717            0 :         painter->drawLine(LineF(lw * .5, ldata->y1, lw * .5, ldata->y2));
     718              :     }
     719            0 :     break;
     720              : 
     721            0 :     case BarLineType::BROKEN: {
     722            0 :         double lw = item->style().styleAbsolute(Sid::dashBarWidth) * item->mag();
     723            0 :         double dl = RealIsNull(lw) ? 0.0 : item->style().styleAbsolute(Sid::dashBarDash) * item->mag() / lw;
     724            0 :         double gl = RealIsNull(lw) ? 0.0 : item->style().styleAbsolute(Sid::dashBarGap) * item->mag() / lw;
     725            0 :         Pen pen(item->curColor(opt), lw, PenStyle::DashLine, PenCapStyle::FlatCap);
     726            0 :         pen.setDashPattern({ dl, gl });
     727            0 :         painter->setPen(pen);
     728            0 :         painter->drawLine(LineF(lw * .5, ldata->y1, lw * .5, ldata->y2));
     729            0 :     }
     730            0 :     break;
     731              : 
     732            0 :     case BarLineType::DOTTED: {
     733            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     734            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::DotLine, PenCapStyle::FlatCap));
     735            0 :         painter->drawLine(LineF(lw * .5, ldata->y1, lw * .5, ldata->y2));
     736              :     }
     737            0 :     break;
     738              : 
     739            0 :     case BarLineType::END: {
     740            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     741            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     742            0 :         double x  = lw * .5;
     743            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     744              : 
     745            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     746            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     747            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     748            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     749              :     }
     750            0 :     break;
     751              : 
     752            0 :     case BarLineType::DOUBLE: {
     753            0 :         double lw = item->style().styleAbsolute(Sid::doubleBarWidth) * item->mag();
     754            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     755            0 :         double x = lw * .5;
     756            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     757            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::doubleBarDistance) + (lw * .5)) * item->mag();
     758            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     759              :     }
     760            0 :     break;
     761              : 
     762            0 :     case BarLineType::REVERSE_END: {
     763            0 :         double lw = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     764            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     765            0 :         double x = lw * .5;
     766            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     767              : 
     768            0 :         double lw2 = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     769            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     770            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     771            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     772              :     }
     773            0 :     break;
     774              : 
     775            0 :     case BarLineType::HEAVY: {
     776            0 :         double lw = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     777            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     778            0 :         painter->drawLine(LineF(lw * .5, ldata->y1, lw * .5, ldata->y2));
     779              :     }
     780            0 :     break;
     781              : 
     782            0 :     case BarLineType::DOUBLE_HEAVY: {
     783            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     784            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     785            0 :         double x = lw2 * .5;
     786            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     787            0 :         x += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     788            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     789              :     }
     790            0 :     break;
     791              : 
     792            0 :     case BarLineType::START_REPEAT: {
     793            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     794            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     795            0 :         double x = lw2 * .5;
     796            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     797              : 
     798            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     799            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     800            0 :         x += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw * .5)) * item->mag();
     801            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     802              : 
     803            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::repeatBarlineDotSeparation)) * item->mag();
     804            0 :         drawDots(item, painter, x);
     805              : 
     806            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     807            0 :             drawTips(item, painter, false, 0.0);
     808              :         }
     809              :     }
     810            0 :     break;
     811              : 
     812            0 :     case BarLineType::END_REPEAT: {
     813            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     814            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     815              : 
     816            0 :         double x = 0.0;
     817            0 :         drawDots(item, painter, x);
     818              : 
     819            0 :         x += item->symBbox(SymId::repeatDot).width();
     820            0 :         x += (item->style().styleAbsolute(Sid::repeatBarlineDotSeparation) + (lw * .5)) * item->mag();
     821            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     822              : 
     823            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     824            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     825            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     826            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     827              : 
     828            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     829            0 :             drawTips(item, painter, true, x + lw2 * .5);
     830              :         }
     831              :     }
     832            0 :     break;
     833            0 :     case BarLineType::END_START_REPEAT: {
     834            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     835            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     836              : 
     837            0 :         double x = 0.0;
     838            0 :         drawDots(item, painter, x);
     839              : 
     840            0 :         x += item->symBbox(SymId::repeatDot).width();
     841            0 :         x += (item->style().styleAbsolute(Sid::repeatBarlineDotSeparation) + (lw * .5)) * item->mag();
     842            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     843              : 
     844            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     845            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     846            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     847            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     848              : 
     849            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     850            0 :             drawTips(item, painter, true, x + lw2 * .5);
     851              :         }
     852              : 
     853            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     854            0 :         x  += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw * .5)) * item->mag();
     855            0 :         painter->drawLine(LineF(x, ldata->y1, x, ldata->y2));
     856              : 
     857            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::repeatBarlineDotSeparation)) * item->mag();
     858            0 :         drawDots(item, painter, x);
     859              : 
     860            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     861            0 :             drawTips(item, painter, false, 0.0);
     862              :         }
     863              :     }
     864            0 :     break;
     865              :     }
     866            0 : }
     867              : 
     868            0 : void SingleDraw::draw(const Beam* item, Painter* painter, const PaintOptions& opt)
     869              : {
     870              :     TRACE_DRAW_ITEM;
     871            0 :     if (item->beamSegments().empty()) {
     872            0 :         return;
     873              :     }
     874            0 :     painter->setBrush(Brush(item->curColor(opt)));
     875            0 :     painter->setNoPen();
     876              : 
     877              :     // make beam thickness independent of slant
     878              :     // (expression can be simplified?)
     879              : 
     880            0 :     const LineF bs = item->beamSegments().front()->line;
     881            0 :     double d  = (std::abs(bs.y2() - bs.y1())) / (bs.x2() - bs.x1());
     882            0 :     if (item->beamSegments().size() > 1 && d > M_PI / 6.0) {
     883            0 :         d = M_PI / 6.0;
     884              :     }
     885            0 :     double ww = (item->beamWidth() / 2.0) / sin(M_PI_2 - atan(d));
     886              : 
     887            0 :     for (const BeamSegment* bs1 : item->beamSegments()) {
     888            0 :         painter->drawPolygon(
     889            0 :             PolygonF({
     890            0 :             PointF(bs1->line.x1(), bs1->line.y1() - ww),
     891            0 :             PointF(bs1->line.x2(), bs1->line.y2() - ww),
     892            0 :             PointF(bs1->line.x2(), bs1->line.y2() + ww),
     893            0 :             PointF(bs1->line.x1(), bs1->line.y1() + ww),
     894            0 :         }),
     895              :             FillRule::OddEvenFill);
     896              :     }
     897              : }
     898              : 
     899            0 : void SingleDraw::draw(const Bend* item, Painter* painter, const PaintOptions& opt)
     900              : {
     901              :     TRACE_DRAW_ITEM;
     902              : 
     903            0 :     const Bend::LayoutData* ldata = item->ldata();
     904            0 :     double _spatium = item->spatium();
     905            0 :     double _lw = item->absoluteFromSpatium(item->lineWidth());
     906              : 
     907            0 :     Pen pen(item->curColor(opt), _lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
     908            0 :     painter->setPen(pen);
     909            0 :     painter->setBrush(Brush(item->curColor(opt)));
     910              : 
     911            0 :     Font f = item->font(_spatium);
     912            0 :     painter->setFont(f);
     913              : 
     914            0 :     double x  = ldata->noteWidth + _spatium * .2;
     915            0 :     double y  = -_spatium * .8;
     916              :     double x2, y2;
     917              : 
     918            0 :     double aw = item->style().styleAbsolute(Sid::bendArrowWidth);
     919            0 :     PolygonF arrowUp;
     920            0 :     arrowUp << PointF(0, 0) << PointF(aw * .5, aw) << PointF(-aw * .5, aw);
     921            0 :     PolygonF arrowDown;
     922            0 :     arrowDown << PointF(0, 0) << PointF(aw * .5, -aw) << PointF(-aw * .5, -aw);
     923              : 
     924            0 :     size_t n = item->points().size();
     925            0 :     for (size_t pt = 0; pt < n - 1; ++pt) {
     926            0 :         int pitch = item->points()[pt].pitch;
     927            0 :         if (pt == 0 && pitch) {
     928            0 :             y2 = -ldata->notePos.y() - _spatium * 2;
     929            0 :             x2 = x;
     930            0 :             painter->drawLine(LineF(x, y, x2, y2));
     931              : 
     932            0 :             painter->setBrush(item->curColor(opt));
     933            0 :             painter->drawPolygon(arrowUp.translated(x2, y2));
     934              : 
     935            0 :             int idx = (pitch + 12) / 25;
     936            0 :             const char* l = item->label[idx];
     937            0 :             painter->drawText(RectF(x2, y2, .0, .0),
     938              :                               muse::draw::AlignHCenter | muse::draw::AlignBottom,
     939              :                               muse::draw::TextDontClip,
     940            0 :                               String::fromAscii(l));
     941              : 
     942            0 :             y = y2;
     943              :         }
     944            0 :         if (pitch == item->points()[pt + 1].pitch) {
     945            0 :             if (pt == (n - 2)) {
     946            0 :                 break;
     947              :             }
     948            0 :             x2 = x + _spatium;
     949            0 :             y2 = y;
     950            0 :             painter->drawLine(LineF(x, y, x2, y2));
     951            0 :         } else if (pitch < item->points()[pt + 1].pitch) {
     952              :             // up
     953            0 :             x2 = x + _spatium * .5;
     954            0 :             y2 = -ldata->notePos.y() - _spatium * 2;
     955            0 :             double dx = x2 - x;
     956            0 :             double dy = y2 - y;
     957              : 
     958            0 :             PainterPath path;
     959            0 :             path.moveTo(x, y);
     960            0 :             path.cubicTo(x + dx / 2, y, x2, y + dy / 4, x2, y2);
     961            0 :             painter->setBrush(BrushStyle::NoBrush);
     962            0 :             painter->drawPath(path);
     963              : 
     964            0 :             painter->setBrush(item->curColor(opt));
     965            0 :             painter->drawPolygon(arrowUp.translated(x2, y2));
     966              : 
     967            0 :             int idx = (item->points()[pt + 1].pitch + 12) / 25;
     968            0 :             const char* l = item->label[idx];
     969            0 :             double ty = y2;       // - _spatium;
     970            0 :             painter->drawText(RectF(x2, ty, .0, .0),
     971              :                               muse::draw::AlignHCenter | muse::draw::AlignBottom,
     972              :                               muse::draw::TextDontClip,
     973            0 :                               String::fromAscii(l));
     974            0 :         } else {
     975              :             // down
     976            0 :             x2 = x + _spatium * .5;
     977            0 :             y2 = y + _spatium * 3;
     978            0 :             double dx = x2 - x;
     979            0 :             double dy = y2 - y;
     980              : 
     981            0 :             PainterPath path;
     982            0 :             path.moveTo(x, y);
     983            0 :             path.cubicTo(x + dx / 2, y, x2, y + dy / 4, x2, y2);
     984            0 :             painter->setBrush(BrushStyle::NoBrush);
     985            0 :             painter->drawPath(path);
     986              : 
     987            0 :             painter->setBrush(item->curColor(opt));
     988            0 :             painter->drawPolygon(arrowDown.translated(x2, y2));
     989            0 :         }
     990            0 :         x = x2;
     991            0 :         y = y2;
     992              :     }
     993            0 : }
     994              : 
     995            0 : void SingleDraw::draw(const Bracket* item, Painter* painter, const PaintOptions& opt)
     996              : {
     997              :     TRACE_DRAW_ITEM;
     998              : 
     999            0 :     const Bracket::LayoutData* ldata = item->ldata();
    1000              : 
    1001            0 :     painter->save();
    1002            0 :     setMask(item, painter);
    1003              : 
    1004            0 :     switch (item->bracketType()) {
    1005            0 :     case BracketType::BRACE: {
    1006            0 :         double h = ldata->bracketHeight;
    1007            0 :         double glyphHeight = item->symHeight(ldata->braceSymbol);
    1008            0 :         double mag = h / glyphHeight;
    1009            0 :         painter->setPen(item->curColor(opt));
    1010            0 :         painter->save();
    1011            0 :         painter->scale(item->magx(), mag);
    1012            0 :         item->drawSymbol(ldata->braceSymbol, painter, PointF(0, glyphHeight));
    1013            0 :         painter->restore();
    1014              :     }
    1015            0 :     break;
    1016            0 :     case BracketType::NORMAL: {
    1017            0 :         double h = ldata->bracketHeight;
    1018            0 :         double _spatium = item->spatium();
    1019            0 :         double w = item->style().styleAbsolute(Sid::bracketWidth);
    1020            0 :         double bd = (item->style().styleSt(Sid::musicalSymbolFont) == "Leland") ? _spatium * .5 : _spatium * .25;
    1021            0 :         Pen pen(item->curColor(opt), w, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1022            0 :         painter->setPen(pen);
    1023            0 :         painter->drawLine(LineF(0.0, -bd - w * .5, 0.0, h + bd + w * .5));
    1024            0 :         double x = -w * .5;
    1025            0 :         double y1 = -bd;
    1026            0 :         double y2 = h + bd;
    1027            0 :         item->drawSymbol(SymId::bracketTop, painter, PointF(x, y1));
    1028            0 :         item->drawSymbol(SymId::bracketBottom, painter, PointF(x, y2));
    1029            0 :     }
    1030            0 :     break;
    1031            0 :     case BracketType::SQUARE:
    1032              :     {
    1033            0 :         double h = ldata->bracketHeight;
    1034            0 :         double lineW = item->style().styleAbsolute(Sid::staffLineWidth);
    1035            0 :         double bracketWidth = ldata->bracketWidth - lineW / 2;
    1036            0 :         Pen pen(item->curColor(opt), lineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1037            0 :         painter->setPen(pen);
    1038            0 :         painter->drawLine(LineF(0.0, 0.0, 0.0, h));
    1039            0 :         painter->drawLine(LineF(-lineW / 2, 0.0, lineW / 2 + bracketWidth, 0.0));
    1040            0 :         painter->drawLine(LineF(-lineW / 2, h, lineW / 2 + bracketWidth, h));
    1041            0 :     }
    1042            0 :     break;
    1043            0 :     case BracketType::LINE: {
    1044            0 :         double h = ldata->bracketHeight;
    1045            0 :         double w = 0.67 * item->style().styleAbsolute(Sid::bracketWidth);
    1046            0 :         Pen pen(item->curColor(opt), w, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1047            0 :         painter->setPen(pen);
    1048            0 :         double bd = item->style().styleAbsolute(Sid::staffLineWidth) * 0.5;
    1049            0 :         painter->drawLine(LineF(0.0, -bd, 0.0, h + bd));
    1050            0 :     }
    1051            0 :     break;
    1052            0 :     case BracketType::GROUP:
    1053              :     {
    1054            0 :         double h = ldata->bracketHeight;
    1055            0 :         double lineW = item->style().styleAbsolute(Sid::staffLineWidth);
    1056            0 :         double bracketWidth = ldata->bracketWidth;
    1057            0 :         Pen pen(item->curColor(opt), lineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1058            0 :         painter->setPen(pen);
    1059            0 :         painter->drawLine(LineF(0.5 * lineW, 0.0, 0.5 * lineW, h));
    1060            0 :         painter->drawLine(LineF(0.0, 0.0, bracketWidth, 0.0));
    1061            0 :         painter->drawLine(LineF(0.0, h, bracketWidth, h));
    1062            0 :     }
    1063            0 :     break;
    1064            0 :     case BracketType::NO_BRACKET:
    1065            0 :         break;
    1066              :     }
    1067              : 
    1068            0 :     painter->restore();
    1069            0 : }
    1070              : 
    1071            0 : void SingleDraw::draw(const Breath* item, Painter* painter, const PaintOptions& opt)
    1072              : {
    1073              :     TRACE_DRAW_ITEM;
    1074            0 :     painter->setPen(item->curColor(opt));
    1075            0 :     item->drawSymbol(item->symId(), painter);
    1076            0 : }
    1077              : 
    1078            0 : void SingleDraw::draw(const ChordLine* item, Painter* painter, const PaintOptions& opt)
    1079              : {
    1080              :     TRACE_DRAW_ITEM;
    1081            0 :     const ChordLine::LayoutData* ldata = item->ldata();
    1082            0 :     IF_ASSERT_FAILED(ldata) {
    1083            0 :         return;
    1084              :     }
    1085              : 
    1086            0 :     if (!item->isWavy()) {
    1087            0 :         painter->setPen(Pen(item->curColor(opt), item->style().styleAbsolute(Sid::chordlineThickness) * item->mag(), PenStyle::SolidLine));
    1088            0 :         painter->setBrush(BrushStyle::NoBrush);
    1089            0 :         painter->drawPath(ldata->path);
    1090              :     } else {
    1091            0 :         painter->save();
    1092            0 :         painter->rotate((item->chordLineType() == ChordLineType::FALL ? 1 : -1));
    1093            0 :         item->drawSymbol(item->waveSym(), painter);
    1094            0 :         painter->restore();
    1095              :     }
    1096              : }
    1097              : 
    1098            0 : void SingleDraw::draw(const Clef* item, Painter* painter, const PaintOptions& opt)
    1099              : {
    1100              :     TRACE_DRAW_ITEM;
    1101            0 :     const Clef::LayoutData* ldata = item->ldata();
    1102            0 :     IF_ASSERT_FAILED(ldata) {
    1103            0 :         return;
    1104              :     }
    1105              : 
    1106            0 :     if (ldata->symId == SymId::noSym) {
    1107            0 :         return;
    1108              :     }
    1109            0 :     painter->setPen(item->curColor(opt));
    1110            0 :     item->drawSymbol(ldata->symId, painter);
    1111              : }
    1112              : 
    1113            0 : void SingleDraw::draw(const Capo* item, Painter* painter, const PaintOptions& opt)
    1114              : {
    1115            0 :     drawTextBase(item, painter, opt);
    1116            0 : }
    1117              : 
    1118            0 : void SingleDraw::draw(const DeadSlapped* item, Painter* painter, const PaintOptions& opt)
    1119              : {
    1120              :     TRACE_DRAW_ITEM;
    1121            0 :     const DeadSlapped::LayoutData* ldata = item->ldata();
    1122            0 :     IF_ASSERT_FAILED(ldata) {
    1123            0 :         return;
    1124              :     }
    1125              : 
    1126            0 :     painter->setPen(PenStyle::NoPen);
    1127            0 :     painter->setBrush(item->curColor(opt));
    1128            0 :     painter->drawPath(ldata->path1);
    1129            0 :     painter->drawPath(ldata->path2);
    1130              : }
    1131              : 
    1132            0 : void SingleDraw::draw(const Dynamic* item, Painter* painter, const PaintOptions& opt)
    1133              : {
    1134            0 :     drawTextBase(item, painter, opt);
    1135            0 : }
    1136              : 
    1137            0 : void SingleDraw::draw(const Expression* item, Painter* painter, const PaintOptions& opt)
    1138              : {
    1139            0 :     drawTextBase(item, painter, opt);
    1140            0 : }
    1141              : 
    1142            0 : void SingleDraw::draw(const Fermata* item, Painter* painter, const PaintOptions& opt)
    1143              : {
    1144              :     TRACE_DRAW_ITEM;
    1145            0 :     painter->setPen(item->curColor(opt));
    1146            0 :     item->drawSymbol(item->symId(), painter, PointF(-0.5 * item->width(), 0.0));
    1147            0 : }
    1148              : 
    1149            0 : void SingleDraw::draw(const FiguredBass* item, Painter* painter, const PaintOptions& opt)
    1150              : {
    1151              :     TRACE_DRAW_ITEM;
    1152            0 :     if (item->items().size() < 1) { // if not parseable into f.b. items
    1153            0 :         drawTextBase(item, painter, opt); // draw as standard text
    1154              :     } else {
    1155            0 :         for (FiguredBassItem* fi : item->items()) { // if parseable into f.b. items
    1156            0 :             painter->translate(fi->pos()); // draw each item in its proper position
    1157            0 :             draw(fi, painter, opt);
    1158            0 :             painter->translate(-fi->pos());
    1159              :         }
    1160              :     }
    1161            0 : }
    1162              : 
    1163            0 : void SingleDraw::draw(const FiguredBassItem* item, Painter* painter, const PaintOptions& opt)
    1164              : {
    1165              :     TRACE_DRAW_ITEM;
    1166              : 
    1167            0 :     const FiguredBassItem::LayoutData* ldata = item->ldata();
    1168            0 :     int font = 0;
    1169            0 :     double _spatium = item->spatium();
    1170              :     // set font from general style
    1171            0 :     Font f(FiguredBass::FBFonts().at(font).family, Font::Type::Tablature);
    1172              : 
    1173              :     // (use the same font selection as used in layout() above)
    1174            0 :     double m = item->style().styleD(Sid::figuredBassFontSize) * item->spatium() / item->defaultSpatium();
    1175            0 :     f.setPointSizeF(m);
    1176              : 
    1177            0 :     painter->setFont(f);
    1178            0 :     painter->setBrush(BrushStyle::NoBrush);
    1179            0 :     Pen pen(item->figuredBass()->curColor(opt), FiguredBass::FB_CONTLINE_THICKNESS.toAbsolute(_spatium), PenStyle::SolidLine,
    1180            0 :             PenCapStyle::RoundCap);
    1181            0 :     painter->setPen(pen);
    1182            0 :     painter->drawText(ldata->bbox(),
    1183              :                       muse::draw::AlignLeft | muse::draw::AlignTop,
    1184              :                       muse::draw::TextDontClip,
    1185            0 :                       ldata->displayText);
    1186              : 
    1187              :     // continuation line
    1188            0 :     double lineEndX = 0.0;
    1189            0 :     if (item->contLine() != FiguredBassItem::ContLine::NONE) {
    1190            0 :         double lineStartX  = ldata->textWidth;                           // by default, line starts right after text
    1191            0 :         if (lineStartX > 0.0) {
    1192            0 :             lineStartX += FiguredBass::FB_CONTLINE_LEFT_PADDING.toAbsolute(_spatium);          // if some text, give some room after it
    1193              :         }
    1194            0 :         lineEndX = item->figuredBass()->ldata()->printedLineLength;            // by default, line ends with item duration
    1195            0 :         if (lineEndX - lineStartX < 1.0) {                         // if line length < 1 sp, ignore it
    1196            0 :             lineEndX = 0.0;
    1197              :         }
    1198              : 
    1199              :         // if extended cont.line and no closing parenthesis: look at next FB element
    1200            0 :         if (item->contLine() > FiguredBassItem::ContLine::SIMPLE && item->parenth5() == FiguredBassItem::Parenthesis::NONE) {
    1201              :             FiguredBass* nextFB;
    1202              :             // if there is a contiguous FB element
    1203            0 :             if ((nextFB = item->figuredBass()->nextFiguredBass()) != 0) {
    1204              :                 // retrieve the X position (in page coords) of a possible cont. line of nextFB
    1205              :                 // on the same line of 'this'
    1206            0 :                 PointF pgPos = item->pagePos();
    1207            0 :                 double nextContPageX = nextFB->additionalContLineX(pgPos.y());
    1208              :                 // if an additional cont. line has been found, extend up to its initial X coord
    1209            0 :                 if (nextContPageX > 0) {
    1210            0 :                     lineEndX = nextContPageX - pgPos.x() + FiguredBass::FB_CONTLINE_OVERLAP.toAbsolute(_spatium);
    1211              :                 }
    1212              :                 // with a little bit of overlap
    1213              :                 else {
    1214            0 :                     lineEndX = item->figuredBass()->ldata()->lineLength(0);                  // if none found, draw to the duration end
    1215              :                 }
    1216              :             }
    1217              :         }
    1218              :         // if some line, draw it
    1219            0 :         if (lineEndX > 0.0) {
    1220            0 :             double h = ldata->bbox().height() * FiguredBass::FB_CONTLINE_HEIGHT;
    1221            0 :             painter->drawLine(lineStartX, h, lineEndX - ldata->pos().x(), h);
    1222              :         }
    1223              :     }
    1224              : 
    1225              :     // closing cont.line parenthesis
    1226            0 :     if (item->parenth5() != FiguredBassItem::Parenthesis::NONE) {
    1227            0 :         int x = lineEndX > 0.0 ? lineEndX : ldata->textWidth;
    1228            0 :         painter->drawText(RectF(x, 0, ldata->bbox().width(), ldata->bbox().height()),
    1229              :                           muse::draw::AlignLeft | muse::draw::AlignTop,
    1230              :                           muse::draw::TextDontClip,
    1231            0 :                           Char(FiguredBass::FBFonts().at(font).displayParenthesis[int(item->parenth5())].unicode()));
    1232              :     }
    1233            0 : }
    1234              : 
    1235            0 : void SingleDraw::draw(const Fingering* item, Painter* painter, const PaintOptions& opt)
    1236              : {
    1237              :     TRACE_DRAW_ITEM;
    1238            0 :     drawTextBase(item, painter, opt);
    1239            0 : }
    1240              : 
    1241            0 : void SingleDraw::draw(const FretDiagram* item, Painter* painter, const PaintOptions& opt)
    1242              : {
    1243              :     TRACE_DRAW_ITEM;
    1244            0 :     const FretDiagram::LayoutData* ldata = item->ldata();
    1245            0 :     PointF translation = -PointF(ldata->stringDist * (item->strings() - 1), 0);
    1246            0 :     if (item->orientation() == Orientation::HORIZONTAL) {
    1247            0 :         painter->save();
    1248            0 :         painter->rotate(-90);
    1249            0 :         painter->translate(translation);
    1250              :     }
    1251              : 
    1252              :     // Init pen and other values
    1253            0 :     Pen pen(item->curColor(opt));
    1254            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1255            0 :     painter->setBrush(Brush(Color(painter->pen().color())));
    1256              : 
    1257              :     // x2 is the x val of the rightmost string
    1258            0 :     double x2 = (item->strings() - 1) * ldata->stringDist;
    1259              : 
    1260              :     // Draw the nut
    1261            0 :     pen.setWidthF(ldata->nutLineWidth);
    1262            0 :     painter->setPen(pen);
    1263            0 :     painter->drawLine(LineF(-ldata->stringLineWidth * .5, 0.0, x2 + ldata->stringLineWidth * .5, 0.0));
    1264              : 
    1265              :     // Draw strings and frets
    1266            0 :     pen.setWidthF(ldata->stringLineWidth);
    1267            0 :     painter->setPen(pen);
    1268              : 
    1269              :     // y2 is the y val of the bottom fretline
    1270            0 :     double y2 = ldata->fretDist * item->frets();
    1271            0 :     for (int i = 0; i < item->strings(); ++i) {
    1272            0 :         double x = ldata->stringDist * i;
    1273            0 :         painter->drawLine(LineF(x, 0.0, x, y2));
    1274              :     }
    1275            0 :     for (int i = 1; i <= item->frets(); ++i) {
    1276            0 :         double y = ldata->fretDist * i;
    1277            0 :         painter->drawLine(LineF(0.0, y, x2, y));
    1278              :     }
    1279              : 
    1280              :     // dotd is the diameter of a dot
    1281            0 :     double dotd = item->style().styleAbsolute(Sid::fretDotSpatiumSize);
    1282              : 
    1283              :     // Draw dots, sym pen is used to draw them (and markers)
    1284            0 :     Pen symPen(pen);
    1285            0 :     symPen.setCapStyle(PenCapStyle::RoundCap);
    1286            0 :     double symPenWidth = ldata->stringLineWidth * 1.2;
    1287            0 :     symPen.setWidthF(symPenWidth);
    1288              : 
    1289            0 :     for (auto const& i : item->dots()) {
    1290            0 :         for (auto const& d : i.second) {
    1291            0 :             if (!d.exists()) {
    1292            0 :                 continue;
    1293              :             }
    1294              : 
    1295            0 :             int string = i.first;
    1296            0 :             int fret = d.fret - 1;
    1297              : 
    1298              :             // Calculate coords of the top left corner of the dot
    1299            0 :             double x = ldata->stringDist * string - dotd * .5;
    1300            0 :             double y = ldata->fretDist * fret + ldata->fretDist * .5 - dotd * .5;
    1301              : 
    1302              :             // Draw different symbols
    1303            0 :             painter->setPen(symPen);
    1304            0 :             switch (d.dtype) {
    1305            0 :             case FretDotType::CROSS:
    1306              :                 // Give the cross a slightly larger width
    1307            0 :                 symPen.setWidthF(symPenWidth * 1.5);
    1308            0 :                 painter->setPen(symPen);
    1309            0 :                 painter->drawLine(LineF(x, y, x + dotd, y + dotd));
    1310            0 :                 painter->drawLine(LineF(x + dotd, y, x, y + dotd));
    1311            0 :                 symPen.setWidthF(symPenWidth);
    1312            0 :                 break;
    1313            0 :             case FretDotType::SQUARE:
    1314            0 :                 painter->setBrush(BrushStyle::NoBrush);
    1315            0 :                 painter->drawRect(RectF(x, y, dotd, dotd));
    1316            0 :                 break;
    1317            0 :             case FretDotType::TRIANGLE:
    1318            0 :                 painter->drawLine(LineF(x, y + dotd, x + .5 * dotd, y));
    1319            0 :                 painter->drawLine(LineF(x + .5 * dotd, y, x + dotd, y + dotd));
    1320            0 :                 painter->drawLine(LineF(x + dotd, y + dotd, x, y + dotd));
    1321            0 :                 break;
    1322            0 :             case FretDotType::NORMAL:
    1323              :             default:
    1324            0 :                 painter->setBrush(symPen.color());
    1325            0 :                 painter->setNoPen();
    1326            0 :                 painter->drawEllipse(RectF(x, y, dotd, dotd));
    1327            0 :                 break;
    1328              :             }
    1329              :         }
    1330              :     }
    1331              : 
    1332              :     // Draw markers
    1333            0 :     symPen.setWidthF(symPenWidth * 1.2);
    1334            0 :     painter->setBrush(BrushStyle::NoBrush);
    1335            0 :     painter->setPen(symPen);
    1336            0 :     for (auto const& i : item->markers()) {
    1337            0 :         int string = i.first;
    1338            0 :         FretItem::Marker marker = i.second;
    1339            0 :         if (!marker.exists()) {
    1340            0 :             continue;
    1341              :         }
    1342              : 
    1343            0 :         double x = ldata->stringDist * string - ldata->markerSize * .5;
    1344            0 :         double y = -ldata->fretDist - ldata->markerSize * .5;
    1345            0 :         if (marker.mtype == FretMarkerType::CIRCLE) {
    1346            0 :             painter->drawEllipse(RectF(x, y, ldata->markerSize, ldata->markerSize));
    1347            0 :         } else if (marker.mtype == FretMarkerType::CROSS) {
    1348            0 :             painter->drawLine(PointF(x, y), PointF(x + ldata->markerSize, y + ldata->markerSize));
    1349            0 :             painter->drawLine(PointF(x, y + ldata->markerSize), PointF(x + ldata->markerSize, y));
    1350              :         }
    1351              :     }
    1352              : 
    1353              :     // Draw barres
    1354            0 :     for (auto const& i : item->barres()) {
    1355            0 :         int fret        = i.first;
    1356            0 :         int startString = i.second.startString;
    1357            0 :         int endString   = i.second.endString;
    1358              : 
    1359            0 :         double x1    = ldata->stringDist * startString;
    1360            0 :         double newX2 = endString == -1 ? x2 : ldata->stringDist * endString;
    1361            0 :         double y     = ldata->fretDist * (fret - 1) + ldata->fretDist * .5;
    1362            0 :         pen.setWidthF(dotd * item->style().styleD(Sid::barreLineWidth));
    1363            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    1364            0 :         painter->setPen(pen);
    1365            0 :         painter->drawLine(LineF(x1, y, newX2, y));
    1366              :     }
    1367              : 
    1368              :     // Draw fret offset number
    1369            0 :     if (item->fretOffset() > 0) {
    1370            0 :         Font scaledFont(item->fretNumFont());
    1371            0 :         scaledFont.setPointSizeF(scaledFont.pointSizeF() * (item->spatium() / item->defaultSpatium()));
    1372            0 :         painter->setFont(scaledFont);
    1373            0 :         String text = String::number(item->fretOffset() + 1);
    1374              : 
    1375            0 :         if (item->orientation() == Orientation::VERTICAL) {
    1376            0 :             if (item->numPos() == 0) {
    1377            0 :                 painter->drawText(RectF(-ldata->stringDist * .4, .0, .0, ldata->fretDist),
    1378              :                                   muse::draw::AlignVCenter | muse::draw::AlignRight,
    1379              :                                   muse::draw::TextDontClip,
    1380              :                                   text);
    1381              :             } else {
    1382            0 :                 painter->drawText(RectF(x2 + (ldata->stringDist * .4), .0, .0, ldata->fretDist),
    1383              :                                   muse::draw::AlignVCenter | muse::draw::AlignLeft,
    1384              :                                   muse::draw::TextDontClip,
    1385            0 :                                   String::number(item->fretOffset() + 1));
    1386              :             }
    1387            0 :         } else if (item->orientation() == Orientation::HORIZONTAL) {
    1388            0 :             painter->save();
    1389            0 :             painter->translate(-translation);
    1390            0 :             painter->rotate(90);
    1391            0 :             if (item->numPos() == 0) {
    1392            0 :                 painter->drawText(RectF(.0, ldata->stringDist * (item->strings() - 1), .0, .0),
    1393              :                                   muse::draw::AlignLeft,
    1394              :                                   muse::draw::TextDontClip,
    1395              :                                   text);
    1396              :             } else {
    1397            0 :                 painter->drawText(RectF(.0, .0, .0, .0),
    1398              :                                   muse::draw::AlignBottom | muse::draw::AlignLeft,
    1399              :                                   muse::draw::TextDontClip,
    1400              :                                   text);
    1401              :             }
    1402            0 :             painter->restore();
    1403              :         }
    1404            0 :         painter->setFont(item->fretNumFont());
    1405            0 :     }
    1406              : 
    1407              :     // NOTE:JT possible future todo - draw fingerings
    1408              : 
    1409            0 :     if (item->orientation() == Orientation::HORIZONTAL) {
    1410            0 :         painter->restore();
    1411              :     }
    1412            0 : }
    1413              : 
    1414            0 : void SingleDraw::draw(const GlissandoSegment* item, Painter* painter, const PaintOptions& opt)
    1415              : {
    1416              :     TRACE_DRAW_ITEM;
    1417              : 
    1418            0 :     if (item->pos2().x() <= 0) {
    1419            0 :         return;
    1420              :     }
    1421              : 
    1422            0 :     painter->save();
    1423            0 :     double _spatium = item->spatium();
    1424            0 :     const Glissando* glissando = item->glissando();
    1425              : 
    1426            0 :     Pen pen(item->curColor(item->visible(), glissando->lineColor(), opt));
    1427            0 :     pen.setWidthF(item->absoluteFromSpatium(item->lineWidth()));
    1428            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1429            0 :     painter->setPen(pen);
    1430              : 
    1431              :     // rotate painter so that the line become horizontal
    1432            0 :     double w     = item->pos2().x();
    1433            0 :     double h     = item->pos2().y();
    1434            0 :     double l     = sqrt(w * w + h * h);
    1435            0 :     double wi    = asin(-h / l) * 180.0 / M_PI;
    1436            0 :     painter->rotate(-wi);
    1437              : 
    1438            0 :     if (glissando->glissandoType() == GlissandoType::STRAIGHT) {
    1439            0 :         painter->drawLine(LineF(0.0, 0.0, l, 0.0));
    1440            0 :     } else if (glissando->glissandoType() == GlissandoType::WAVY) {
    1441            0 :         RectF b = item->symBbox(SymId::wiggleTrill);
    1442            0 :         double a  = item->symAdvance(SymId::wiggleTrill);
    1443            0 :         int n    = static_cast<int>(l / a);          // always round down (truncate) to avoid overlap
    1444            0 :         double x  = (l - n * a) * 0.5;     // centre line in available space
    1445            0 :         SymIdList ids;
    1446            0 :         for (int i = 0; i < n; ++i) {
    1447            0 :             ids.push_back(SymId::wiggleTrill);
    1448              :         }
    1449              : 
    1450            0 :         item->drawSymbols(ids, painter, PointF(x, -(b.y() + b.height() * 0.5)));
    1451            0 :     }
    1452              : 
    1453            0 :     if (glissando->showText()) {
    1454            0 :         Font f(glissando->fontFace(), Font::Type::Unknown);
    1455            0 :         f.setPointSizeF(glissando->fontSize() * _spatium / item->defaultSpatium());
    1456            0 :         f.setBold(glissando->fontStyle() & FontStyle::Bold);
    1457            0 :         f.setItalic(glissando->fontStyle() & FontStyle::Italic);
    1458            0 :         f.setUnderline(glissando->fontStyle() & FontStyle::Underline);
    1459            0 :         f.setStrike(glissando->fontStyle() & FontStyle::Strike);
    1460            0 :         FontMetrics fm(f);
    1461            0 :         RectF r = fm.boundingRect(glissando->text());
    1462              : 
    1463              :         // if text longer than available space, skip it
    1464            0 :         if (r.width() < l) {
    1465            0 :             double yOffset = r.height() + r.y();             // find text descender height
    1466              :             // raise text slightly above line and slightly more with WAVY than with STRAIGHT
    1467            0 :             yOffset += _spatium * (glissando->glissandoType() == GlissandoType::WAVY ? 0.4 : 0.1);
    1468              : 
    1469            0 :             painter->setFont(f);
    1470              : 
    1471            0 :             double x = (l - r.width()) * 0.5;
    1472            0 :             painter->drawText(PointF(x, -yOffset), glissando->text());
    1473              :         }
    1474            0 :     }
    1475            0 :     painter->restore();
    1476            0 : }
    1477              : 
    1478            0 : void SingleDraw::draw(const Stem* item, Painter* painter, const PaintOptions& opt)
    1479              : {
    1480              :     TRACE_DRAW_ITEM;
    1481            0 :     if (!item->chord()) { // may be need assert?
    1482            0 :         return;
    1483              :     }
    1484              : 
    1485              :     // hide if second chord of a cross-measure pair
    1486            0 :     if (item->chord()->crossMeasure() == CrossMeasure::SECOND) {
    1487            0 :         return;
    1488              :     }
    1489              : 
    1490            0 :     const Stem::LayoutData* ldata = item->ldata();
    1491            0 :     const Staff* staff = item->staff();
    1492            0 :     const StaffType* staffType = staff ? staff->staffTypeForElement(item->chord()) : nullptr;
    1493            0 :     const bool isTablature = staffType && staffType->isTabStaff();
    1494              : 
    1495            0 :     painter->setPen(Pen(item->curColor(opt), item->lineWidthMag(), PenStyle::SolidLine, PenCapStyle::FlatCap));
    1496            0 :     painter->drawLine(ldata->line);
    1497              : 
    1498            0 :     if (!isTablature) {
    1499            0 :         return;
    1500              :     }
    1501              : 
    1502              :     // TODO: adjust bounding rectangle in layout() for dots and for slash
    1503            0 :     double sp = item->spatium();
    1504            0 :     bool isUp = item->up();
    1505              : 
    1506              :     // slashed half note stem
    1507            0 :     if (item->chord()->durationType().type() == DurationType::V_HALF
    1508            0 :         && staffType->minimStyle() == TablatureMinimStyle::SLASHED) {
    1509              :         // position slashes onto stem
    1510            0 :         double y = isUp ? -item->length() + score::StemLayout::STAFFTYPE_TAB_SLASH_2STARTY_UP * sp
    1511            0 :                    : item->length() - score::StemLayout::STAFFTYPE_TAB_SLASH_2STARTY_DN * sp;
    1512              :         // if stems through, try to align slashes within or across lines
    1513            0 :         if (staffType->stemThrough()) {
    1514            0 :             double halfLineDist = staffType->lineDistance().val() * sp * 0.5;
    1515            0 :             double halfSlashHgt = score::StemLayout::STAFFTYPE_TAB_SLASH_2TOTHEIGHT * sp * 0.5;
    1516            0 :             y = lrint((y + halfSlashHgt) / halfLineDist) * halfLineDist - halfSlashHgt;
    1517              :         }
    1518              :         // draw slashes
    1519            0 :         double hlfWdt= sp * score::StemLayout::STAFFTYPE_TAB_SLASH_WIDTH * 0.5;
    1520            0 :         double sln   = sp * score::StemLayout::STAFFTYPE_TAB_SLASH_SLANTY;
    1521            0 :         double thk   = sp * score::StemLayout::STAFFTYPE_TAB_SLASH_THICK;
    1522            0 :         double displ = sp * score::StemLayout::STAFFTYPE_TAB_SLASH_DISPL;
    1523            0 :         PainterPath path;
    1524            0 :         for (int i = 0; i < 2; ++i) {
    1525            0 :             path.moveTo(hlfWdt, y);                   // top-right corner
    1526            0 :             path.lineTo(hlfWdt, y + thk);             // bottom-right corner
    1527            0 :             path.lineTo(-hlfWdt, y + thk + sln);      // bottom-left corner
    1528            0 :             path.lineTo(-hlfWdt, y + sln);            // top-left corner
    1529            0 :             path.closeSubpath();
    1530            0 :             y += displ;
    1531              :         }
    1532            0 :         painter->setBrush(Brush(item->curColor(opt)));
    1533            0 :         painter->setNoPen();
    1534            0 :         painter->drawPath(path);
    1535            0 :     }
    1536              : 
    1537              :     // dots
    1538              :     // NOT THE BEST PLACE FOR THIS?
    1539              :     // with tablatures and stems beside staves, dots are not drawn near 'notes', but near stems
    1540            0 :     int nDots = item->chord()->dots();
    1541            0 :     if (nDots > 0 && !staffType->stemThrough()) {
    1542            0 :         double x     = item->chord()->dotPosX();
    1543            0 :         double y     = ((score::StemLayout::STAFFTYPE_TAB_DEFAULTSTEMLEN_DN * 0.2) * sp) * (isUp ? -1.0 : 1.0);
    1544            0 :         double step  = item->style().styleS(Sid::dotDotDistance).val() * sp;
    1545            0 :         for (int dot = 0; dot < nDots; dot++, x += step) {
    1546            0 :             item->drawSymbol(SymId::augmentationDot, painter, PointF(x, y));
    1547              :         }
    1548              :     }
    1549              : }
    1550              : 
    1551            0 : void SingleDraw::draw(const StemSlash* item, Painter* painter, const PaintOptions& opt)
    1552              : {
    1553              :     TRACE_DRAW_ITEM;
    1554              : 
    1555            0 :     const StemSlash::LayoutData* ldata = item->ldata();
    1556            0 :     painter->setPen(Pen(item->curColor(opt), ldata->stemWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    1557            0 :     painter->drawLine(ldata->line);
    1558            0 : }
    1559              : 
    1560            0 : void SingleDraw::draw(const Sticking* item, Painter* painter, const PaintOptions& opt)
    1561              : {
    1562              :     TRACE_DRAW_ITEM;
    1563            0 :     drawTextBase(item, painter, opt);
    1564            0 : }
    1565              : 
    1566            0 : void SingleDraw::draw(const StringTunings* item, Painter* painter, const PaintOptions& opt)
    1567              : {
    1568              :     TRACE_DRAW_ITEM;
    1569            0 :     drawTextBase(item, painter, opt);
    1570            0 : }
    1571              : 
    1572            0 : void SingleDraw::drawTextBase(const TextBase* item, Painter* painter, const PaintOptions& opt)
    1573              : {
    1574              :     TRACE_DRAW_ITEM;
    1575              : 
    1576            0 :     painter->save();
    1577            0 :     painter->rotate(item->textAngle());
    1578              : 
    1579            0 :     const TextBase::LayoutData* ldata = item->ldata();
    1580              : 
    1581            0 :     if (item->hasFrame()) {
    1582            0 :         double baseSpatium = DefaultStyle::baseStyle().value(Sid::spatium).toReal();
    1583            0 :         if (!RealIsNull(item->frameWidth().val())) {
    1584            0 :             Color fColor = item->curColor(item->visible(), item->frameColor(), opt);
    1585            0 :             double frameWidthVal = item->frameWidth().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    1586              : 
    1587            0 :             Pen pen(fColor, frameWidthVal, PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin);
    1588            0 :             painter->setPen(pen);
    1589            0 :         } else {
    1590            0 :             painter->setNoPen();
    1591              :         }
    1592            0 :         Color bg(item->bgColor());
    1593            0 :         painter->setBrush(bg.alpha() ? Brush(bg) : BrushStyle::NoBrush);
    1594            0 :         if (item->circle()) {
    1595            0 :             painter->drawEllipse(ldata->frame);
    1596              :         } else {
    1597            0 :             double frameRadius = item->frameRound().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    1598            0 :             painter->drawRoundedRect(ldata->frame, frameRadius, frameRadius);
    1599              :         }
    1600              :     }
    1601            0 :     painter->setBrush(BrushStyle::NoBrush);
    1602            0 :     painter->setPen(item->textColor(opt));
    1603            0 :     for (const TextBlock& t : ldata->blocks) {
    1604            0 :         draw(t, item, painter);
    1605              :     }
    1606              : 
    1607            0 :     painter->restore();
    1608            0 : }
    1609              : 
    1610            0 : void SingleDraw::draw(const TextBlock& textBlock, const TextBase* item, muse::draw::Painter* painter)
    1611              : {
    1612            0 :     painter->translate(0.0, textBlock.y());
    1613            0 :     for (const TextFragment& f : textBlock.fragments()) {
    1614            0 :         draw(f, item, painter);
    1615              :     }
    1616            0 :     painter->translate(0.0, -textBlock.y());
    1617            0 : }
    1618              : 
    1619            0 : void SingleDraw::draw(const TextFragment& textFragment, const TextBase* item, muse::draw::Painter* painter)
    1620              : {
    1621            0 :     painter->setFont(textFragment.font(item));
    1622            0 :     painter->drawText(textFragment.pos, textFragment.text);
    1623            0 : }
    1624              : 
    1625            0 : static void setDashAndGapLen(const SLine* line, double& dash, double& gap, Pen& pen)
    1626              : {
    1627              :     static constexpr double DOTTED_DASH_LEN = 0.01;
    1628              :     static constexpr double DOTTED_GAP_LEN = 1.99;
    1629            0 :     switch (line->lineStyle()) {
    1630            0 :     case LineType::SOLID:
    1631            0 :         break;
    1632            0 :     case LineType::DASHED:
    1633            0 :         dash = line->dashLineLen(), gap = line->dashGapLen();
    1634            0 :         break;
    1635            0 :     case LineType::DOTTED:
    1636            0 :         dash = DOTTED_DASH_LEN, gap = DOTTED_GAP_LEN;
    1637            0 :         pen.setCapStyle(PenCapStyle::RoundCap); // round dots
    1638            0 :         break;
    1639              :     }
    1640            0 : }
    1641              : 
    1642            0 : static std::vector<double> distributedDashPattern(double dash, double gap, double lineLength)
    1643              : {
    1644            0 :     int numPairs = std::max(1.0, lineLength / (dash + gap));
    1645            0 :     double newGap = (lineLength - dash * (numPairs + 1)) / numPairs;
    1646              : 
    1647            0 :     return { dash, newGap };
    1648              : }
    1649              : 
    1650            0 : void SingleDraw::drawTextLineBaseSegment(const TextLineBaseSegment* item, Painter* painter, const PaintOptions& opt)
    1651              : {
    1652            0 :     const TextLineBase* tl = item->textLineBase();
    1653            0 :     const TextLineBaseSegment::LayoutData* ldata = item->ldata();
    1654              : 
    1655            0 :     if (!item->text()->empty()) {
    1656            0 :         painter->translate(item->text()->pos());
    1657            0 :         item->text()->setVisible(tl->visible());
    1658            0 :         draw(item->text(), painter, opt);
    1659            0 :         painter->translate(-item->text()->pos());
    1660              :     }
    1661              : 
    1662            0 :     if (!item->endText()->empty()) {
    1663            0 :         painter->translate(item->endText()->pos());
    1664            0 :         item->endText()->setVisible(tl->visible());
    1665            0 :         draw(item->endText(), painter, opt);
    1666            0 :         painter->translate(-item->endText()->pos());
    1667              :     }
    1668              : 
    1669            0 :     if (ldata->npoints == 0) {
    1670            0 :         return;
    1671              :     }
    1672              : 
    1673              :     // color for line (text color comes from the text properties)
    1674            0 :     Color color = item->curColor(tl->visible() && tl->lineVisible(), tl->lineColor(), opt);
    1675              : 
    1676            0 :     double lineWidth = tl->absoluteFromSpatium(tl->lineWidth());
    1677              : 
    1678            0 :     const Pen solidPen(color, lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap, PenJoinStyle::MiterJoin);
    1679            0 :     Pen pen(solidPen);
    1680              : 
    1681            0 :     double dash = 0;
    1682            0 :     double gap = 0;
    1683              : 
    1684            0 :     setDashAndGapLen(tl, dash, gap, pen);
    1685              : 
    1686            0 :     const bool isNonSolid = tl->lineStyle() != LineType::SOLID;
    1687              : 
    1688              :     // Draw lines
    1689            0 :     if (item->twoLines()) { // hairpins
    1690            0 :         if (isNonSolid) {
    1691            0 :             pen.setDashPattern({ dash, gap });
    1692              :         }
    1693              : 
    1694            0 :         pen.setJoinStyle(PenJoinStyle::BevelJoin);
    1695            0 :         painter->setPen(pen);
    1696            0 :         if (!ldata->joinedHairpin.empty() && !isNonSolid) {
    1697            0 :             painter->drawPolyline(ldata->joinedHairpin);
    1698              :         } else {
    1699            0 :             painter->drawLines(&ldata->points[0], 2);
    1700              :         }
    1701            0 :         return;
    1702              :     }
    1703              : 
    1704            0 :     int start = 0, end = ldata->npoints;
    1705              : 
    1706              :     // Draw begin hook, if it needs to be drawn separately
    1707            0 :     if (item->isSingleBeginType() && tl->beginHookType() != HookType::NONE) {
    1708            0 :         if (tl->beginHookType() == HookType::ARROW_FILLED) {
    1709            0 :             Brush brush;
    1710            0 :             brush.setStyle(BrushStyle::SolidPattern);
    1711            0 :             brush.setColor(item->curColor(opt));
    1712            0 :             painter->setBrush(brush);
    1713            0 :             painter->setNoPen();
    1714            0 :             painter->drawPolygon(ldata->beginArrow);
    1715            0 :         } else if (tl->beginHookType() == HookType::ARROW) {
    1716            0 :             pen.setJoinStyle(PenJoinStyle::MiterJoin);
    1717            0 :             painter->setPen(pen);
    1718            0 :             painter->drawPolyline(ldata->beginArrow);
    1719              :         } else {
    1720            0 :             bool isTHook = tl->beginHookType() == HookType::HOOK_90T;
    1721              : 
    1722            0 :             if (isNonSolid || isTHook) {
    1723            0 :                 const PointF& p1 = ldata->points[start++];
    1724            0 :                 const PointF& p2 = ldata->points[start++];
    1725              : 
    1726            0 :                 if (isTHook) {
    1727            0 :                     painter->setPen(solidPen);
    1728              :                 } else {
    1729            0 :                     double hookLength = sqrt(PointF::dotProduct(p2 - p1, p2 - p1));
    1730            0 :                     pen.setDashPattern(distributedDashPattern(dash, gap, hookLength / lineWidth));
    1731            0 :                     painter->setPen(pen);
    1732              :                 }
    1733              : 
    1734            0 :                 painter->drawLine(p1, p2);
    1735              :             }
    1736              :         }
    1737              :     }
    1738              : 
    1739              :     // Draw end hook, if it needs to be drawn separately
    1740            0 :     if (item->isSingleEndType() && tl->endHookType() != HookType::NONE) {
    1741            0 :         if (tl->endHookType() == HookType::ARROW_FILLED) {
    1742            0 :             Brush brush;
    1743            0 :             brush.setStyle(BrushStyle::SolidPattern);
    1744            0 :             brush.setColor(item->curColor(opt));
    1745            0 :             painter->setBrush(brush);
    1746            0 :             painter->setNoPen();
    1747            0 :             painter->drawPolygon(ldata->endArrow);
    1748            0 :         } else if (tl->endHookType() == HookType::ARROW) {
    1749            0 :             pen.setJoinStyle(PenJoinStyle::MiterJoin);
    1750            0 :             painter->setPen(pen);
    1751            0 :             painter->drawPolyline(ldata->endArrow);
    1752              :         } else {
    1753            0 :             bool isTHook = tl->endHookType() == HookType::HOOK_90T;
    1754              : 
    1755            0 :             if (isNonSolid || isTHook) {
    1756            0 :                 const PointF& p1 = ldata->points[--end];
    1757            0 :                 const PointF& p2 = ldata->points[--end];
    1758              : 
    1759            0 :                 if (isTHook) {
    1760            0 :                     painter->setPen(solidPen);
    1761              :                 } else {
    1762            0 :                     double hookLength = sqrt(PointF::dotProduct(p2 - p1, p2 - p1));
    1763            0 :                     pen.setDashPattern(distributedDashPattern(dash, gap, hookLength / lineWidth));
    1764            0 :                     painter->setPen(pen);
    1765              :                 }
    1766              : 
    1767            0 :                 painter->drawLine(p1, p2);
    1768              :             }
    1769              :         }
    1770              :     }
    1771              : 
    1772              :     // Draw the rest
    1773            0 :     if (isNonSolid) {
    1774            0 :         pen.setDashPattern(distributedDashPattern(dash, gap, ldata->lineLength / lineWidth));
    1775              :     }
    1776              : 
    1777            0 :     painter->setPen(pen);
    1778            0 :     painter->drawPolyline(&ldata->points[start], end - start);
    1779            0 : }
    1780              : 
    1781            0 : void SingleDraw::draw(const GradualTempoChangeSegment* item, Painter* painter, const PaintOptions& opt)
    1782              : {
    1783              :     TRACE_DRAW_ITEM;
    1784            0 :     drawTextLineBaseSegment(item, painter, opt);
    1785            0 : }
    1786              : 
    1787            0 : void SingleDraw::draw(const GuitarBendSegment*, Painter*, const PaintOptions&)
    1788              : {
    1789              :     // TRACE_DRAW_ITEM;
    1790              :     // To be implemented
    1791            0 : }
    1792              : 
    1793            0 : void SingleDraw::draw(const HairpinSegment* item, Painter* painter, const PaintOptions& opt)
    1794              : {
    1795              :     TRACE_DRAW_ITEM;
    1796              : 
    1797            0 :     drawTextLineBaseSegment(item, painter, opt);
    1798              : 
    1799            0 :     if (item->drawCircledTip()) {
    1800            0 :         Color color = item->curColor(item->hairpin()->visible(), item->hairpin()->lineColor(), opt);
    1801            0 :         double w = item->absoluteFromSpatium(item->lineWidth());
    1802            0 :         if (item->staff()) {
    1803            0 :             w *= item->staff()->staffMag(item->hairpin()->tick());
    1804              :         }
    1805              : 
    1806            0 :         Pen pen(color, w);
    1807            0 :         painter->setPen(pen);
    1808            0 :         painter->setBrush(BrushStyle::NoBrush);
    1809            0 :         painter->drawEllipse(item->circledTip(), item->circledTipRadius(), item->circledTipRadius());
    1810            0 :     }
    1811            0 : }
    1812              : 
    1813            0 : void SingleDraw::draw(const HammerOnPullOffSegment* item, muse::draw::Painter* painter, const PaintOptions& opt)
    1814              : {
    1815            0 :     draw(toSlurSegment(item), painter, opt);
    1816            0 : }
    1817              : 
    1818            0 : void SingleDraw::draw(const HammerOnPullOffText* item, Painter* painter, const PaintOptions& opt)
    1819              : {
    1820            0 :     drawTextBase(item, painter, opt);
    1821            0 : }
    1822              : 
    1823            0 : void SingleDraw::draw(const HarpPedalDiagram* item, Painter* painter, const PaintOptions& opt)
    1824              : {
    1825              :     TRACE_DRAW_ITEM;
    1826            0 :     drawTextBase(item, painter, opt);
    1827            0 : }
    1828              : 
    1829            0 : void SingleDraw::draw(const HarmonicMarkSegment* item, Painter* painter, const PaintOptions& opt)
    1830              : {
    1831              :     TRACE_DRAW_ITEM;
    1832            0 :     drawTextLineBaseSegment(item, painter, opt);
    1833            0 : }
    1834              : 
    1835            0 : void SingleDraw::draw(const Harmony* item, Painter* painter, const PaintOptions& opt)
    1836              : {
    1837              :     TRACE_DRAW_ITEM;
    1838              : 
    1839            0 :     const Harmony::LayoutData* ldata = item->ldata();
    1840            0 :     if (ldata->renderItemList().empty()) {
    1841            0 :         drawTextBase(item, painter, opt);
    1842            0 :         return;
    1843              :     }
    1844              : 
    1845            0 :     if (item->hasFrame()) {
    1846            0 :         if (!RealIsNull(item->frameWidth().val())) {
    1847            0 :             Color color = item->frameColor();
    1848            0 :             Pen pen(color, item->frameWidth().val() * item->spatium(), PenStyle::SolidLine,
    1849            0 :                     PenCapStyle::SquareCap, PenJoinStyle::MiterJoin);
    1850            0 :             painter->setPen(pen);
    1851            0 :         } else {
    1852            0 :             painter->setNoPen();
    1853              :         }
    1854            0 :         Color bg(item->bgColor());
    1855            0 :         painter->setBrush(bg.alpha() ? Brush(bg) : BrushStyle::NoBrush);
    1856            0 :         if (item->circle()) {
    1857            0 :             painter->drawArc(ldata->frame, 0, 5760);
    1858              :         } else {
    1859            0 :             double baseSpatium = DefaultStyle::baseStyle().value(Sid::spatium).toReal();
    1860            0 :             double frameRadius = item->frameRound().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    1861            0 :             painter->drawRoundedRect(ldata->frame, frameRadius, frameRadius);
    1862              :         }
    1863              :     }
    1864            0 :     painter->setBrush(BrushStyle::NoBrush);
    1865            0 :     Color color = item->textColor(opt);
    1866            0 :     painter->setPen(color);
    1867            0 :     for (const HarmonyRenderItem* renderItem : ldata->renderItemList()) {
    1868            0 :         if (const TextSegment* ts = dynamic_cast<const TextSegment*>(renderItem)) {
    1869            0 :             painter->setFont(ts->font());
    1870            0 :             painter->drawText(ts->pos(), ts->text());
    1871              :         }
    1872              :     }
    1873              : }
    1874              : 
    1875            0 : void SingleDraw::draw(const Hook* item, Painter* painter, const PaintOptions& opt)
    1876              : {
    1877              :     TRACE_DRAW_ITEM;
    1878            0 :     painter->setPen(item->curColor(opt));
    1879            0 :     item->drawSymbol(item->sym(), painter);
    1880            0 : }
    1881              : 
    1882            0 : void SingleDraw::draw(const Image* item, Painter* painter, const PaintOptions&)
    1883              : {
    1884              :     TRACE_DRAW_ITEM;
    1885            0 :     const Image::LayoutData* ldata = item->ldata();
    1886            0 :     bool emptyImage = false;
    1887            0 :     if (item->imageType() == ImageType::SVG) {
    1888            0 :         if (!item->svgRenderer()) {
    1889            0 :             emptyImage = true;
    1890              :         } else {
    1891            0 :             item->svgRenderer()->render(painter, ldata->bbox());
    1892              :         }
    1893            0 :     } else if (item->imageType() == ImageType::RASTER) {
    1894            0 :         if (item->rasterImage() == nullptr) {
    1895            0 :             emptyImage = true;
    1896              :         } else {
    1897            0 :             painter->save();
    1898            0 :             SizeF s;
    1899            0 :             if (item->sizeIsSpatium()) {
    1900            0 :                 s = item->size() * item->spatium();
    1901              :             } else {
    1902            0 :                 s = item->size() * DPMM;
    1903              :             }
    1904              : 
    1905            0 :             painter->scale(s.width() / item->rasterImage()->width(), s.height() / item->rasterImage()->height());
    1906            0 :             painter->drawPixmap(PointF(0, 0), *item->rasterImage());
    1907              : 
    1908            0 :             painter->restore();
    1909              :         }
    1910              :     }
    1911              : 
    1912            0 :     if (emptyImage) {
    1913            0 :         painter->setBrush(BrushStyle::NoBrush);
    1914            0 :         painter->setPen(item->configuration()->defaultColor());
    1915            0 :         painter->drawRect(ldata->bbox());
    1916            0 :         painter->drawLine(0.0, 0.0, ldata->bbox().width(), ldata->bbox().height());
    1917            0 :         painter->drawLine(ldata->bbox().width(), 0.0, 0.0, ldata->bbox().height());
    1918              :     }
    1919            0 : }
    1920              : 
    1921            0 : void SingleDraw::draw(const InstrumentChange* item, Painter* painter, const PaintOptions& opt)
    1922              : {
    1923              :     TRACE_DRAW_ITEM;
    1924            0 :     drawTextBase(item, painter, opt);
    1925            0 : }
    1926              : 
    1927            0 : void SingleDraw::draw(const InstrumentName* item, Painter* painter, const PaintOptions& opt)
    1928              : {
    1929              :     TRACE_DRAW_ITEM;
    1930            0 :     drawTextBase(item, painter, opt);
    1931            0 : }
    1932              : 
    1933            0 : void SingleDraw::draw(const Jump* item, Painter* painter, const PaintOptions& opt)
    1934              : {
    1935              :     TRACE_DRAW_ITEM;
    1936            0 :     drawTextBase(item, painter, opt);
    1937            0 : }
    1938              : 
    1939            0 : void SingleDraw::draw(const KeySig* item, Painter* painter, const PaintOptions& opt)
    1940              : {
    1941              :     TRACE_DRAW_ITEM;
    1942              : 
    1943            0 :     const KeySig::LayoutData* ldata = item->ldata();
    1944              : 
    1945            0 :     painter->setPen(item->curColor(opt));
    1946            0 :     double _spatium = item->spatium();
    1947            0 :     double step = _spatium * 0.5;
    1948            0 :     int lines = 5;
    1949            0 :     double ledgerLineWidth = item->style().styleAbsolute(Sid::ledgerLineWidth) * item->mag();
    1950            0 :     double ledgerExtraLen = item->style().styleS(Sid::ledgerLineLength).val() * _spatium;
    1951            0 :     for (const KeySym& ks : ldata->keySymbols) {
    1952            0 :         double x = ks.xPos.toAbsolute(_spatium);
    1953            0 :         double y = ks.line * step;
    1954            0 :         item->drawSymbol(ks.sym, painter, PointF(x, y));
    1955              :         // ledger lines
    1956            0 :         double _symWidth = item->symWidth(ks.sym);
    1957            0 :         double x1 = x - ledgerExtraLen;
    1958            0 :         double x2 = x + _symWidth + ledgerExtraLen;
    1959            0 :         painter->setPen(Pen(item->curColor(opt), ledgerLineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    1960            0 :         for (int i = -2; i >= ks.line; i -= 2) { // above
    1961            0 :             y = i * step;
    1962            0 :             painter->drawLine(LineF(x1, y, x2, y));
    1963              :         }
    1964            0 :         for (int i = lines * 2; i <= ks.line; i += 2) { // below
    1965            0 :             y = i * step;
    1966            0 :             painter->drawLine(LineF(x1, y, x2, y));
    1967              :         }
    1968              :     }
    1969              : 
    1970            0 :     if (!item->ownershipParent() && (item->isAtonal() || item->isCustom()) && ldata->keySymbols.empty()) {
    1971              :         // empty custom or atonal key signature - draw something for palette
    1972            0 :         painter->setPen(item->configuration()->scoreGreyColor());
    1973            0 :         item->drawSymbol(SymId::timeSigX, painter, PointF(item->symWidth(SymId::timeSigX) * -0.5, 2.0 * item->spatium()));
    1974              :     }
    1975            0 : }
    1976              : 
    1977            0 : void SingleDraw::draw(const LayoutBreak* item, Painter* painter, const PaintOptions&)
    1978              : {
    1979              :     TRACE_DRAW_ITEM;
    1980              : 
    1981            0 :     Pen pen(item->configuration()->fontPrimaryColor());
    1982            0 :     painter->setPen(pen);
    1983              : 
    1984            0 :     painter->setFont(item->font());
    1985              : 
    1986            0 :     painter->drawSymbol(PointF(0.0, 0.0), item->iconCode());
    1987            0 : }
    1988              : 
    1989            0 : void SingleDraw::draw(const LedgerLine* item, Painter* painter, const PaintOptions& opt)
    1990              : {
    1991              :     TRACE_DRAW_ITEM;
    1992            0 :     const LedgerLine::LayoutData* ldata = item->ldata();
    1993              : 
    1994            0 :     painter->setPen(Pen(item->curColor(opt), ldata->lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    1995            0 :     if (item->vertical()) {
    1996            0 :         painter->drawLine(LineF(0.0, 0.0, 0.0, item->len()));
    1997              :     } else {
    1998            0 :         painter->drawLine(LineF(0.0, 0.0, item->len(), 0.0));
    1999              :     }
    2000            0 : }
    2001              : 
    2002            0 : void SingleDraw::draw(const LetRingSegment* item, Painter* painter, const PaintOptions& opt)
    2003              : {
    2004              :     TRACE_DRAW_ITEM;
    2005            0 :     drawTextLineBaseSegment(item, painter, opt);
    2006            0 : }
    2007              : 
    2008            0 : void SingleDraw::draw(const Lyrics* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2009              : {
    2010              :     TRACE_DRAW_ITEM;
    2011            0 :     drawTextBase(item, painter, opt);
    2012            0 : }
    2013              : 
    2014            0 : void SingleDraw::draw(const Marker* item, Painter* painter, const PaintOptions& opt)
    2015              : {
    2016              :     TRACE_DRAW_ITEM;
    2017            0 :     drawTextBase(item, painter, opt);
    2018            0 : }
    2019              : 
    2020            0 : void SingleDraw::draw(const MeasureNumber* item, Painter* painter, const PaintOptions& opt)
    2021              : {
    2022              :     TRACE_DRAW_ITEM;
    2023            0 :     drawTextBase(item, painter, opt);
    2024            0 : }
    2025              : 
    2026            0 : void SingleDraw::draw(const MeasureRepeat* item, Painter* painter, const PaintOptions& opt)
    2027              : {
    2028              :     TRACE_DRAW_ITEM;
    2029              : 
    2030            0 :     const MeasureRepeat::LayoutData* ldata = item->ldata();
    2031            0 :     painter->setPen(item->curColor(opt));
    2032            0 :     item->drawSymbol(ldata->symId, painter);
    2033            0 : }
    2034              : 
    2035            0 : void SingleDraw::draw(const OttavaSegment* item, Painter* painter, const PaintOptions& opt)
    2036              : {
    2037              :     TRACE_DRAW_ITEM;
    2038            0 :     drawTextLineBaseSegment(item, painter, opt);
    2039            0 : }
    2040              : 
    2041            0 : void SingleDraw::draw(const PalmMuteSegment* item, Painter* painter, const PaintOptions& opt)
    2042              : {
    2043              :     TRACE_DRAW_ITEM;
    2044            0 :     drawTextLineBaseSegment(item, painter, opt);
    2045            0 : }
    2046              : 
    2047            0 : void SingleDraw::draw(const PedalSegment* item, Painter* painter, const PaintOptions& opt)
    2048              : {
    2049              :     TRACE_DRAW_ITEM;
    2050            0 :     drawTextLineBaseSegment(item, painter, opt);
    2051            0 : }
    2052              : 
    2053            0 : void SingleDraw::draw(const PickScrapeSegment* item, Painter* painter, const PaintOptions& opt)
    2054              : {
    2055              :     TRACE_DRAW_ITEM;
    2056            0 :     drawTextLineBaseSegment(item, painter, opt);
    2057            0 : }
    2058              : 
    2059            0 : void SingleDraw::draw(const PlayCountText* item, Painter* painter, const PaintOptions& opt)
    2060              : {
    2061              :     TRACE_DRAW_ITEM;
    2062            0 :     drawTextBase(item, painter, opt);
    2063            0 : }
    2064              : 
    2065            0 : void SingleDraw::draw(const PlayTechAnnotation* item, Painter* painter, const PaintOptions& opt)
    2066              : {
    2067              :     TRACE_DRAW_ITEM;
    2068            0 :     drawTextBase(item, painter, opt);
    2069            0 : }
    2070              : 
    2071            0 : void SingleDraw::draw(const RasgueadoSegment* item, Painter* painter, const PaintOptions& opt)
    2072              : {
    2073              :     TRACE_DRAW_ITEM;
    2074            0 :     drawTextLineBaseSegment(item, painter, opt);
    2075            0 : }
    2076              : 
    2077            0 : void SingleDraw::draw(const RehearsalMark* item, Painter* painter, const PaintOptions& opt)
    2078              : {
    2079              :     TRACE_DRAW_ITEM;
    2080            0 :     drawTextBase(item, painter, opt);
    2081            0 : }
    2082              : 
    2083            0 : void SingleDraw::draw(const Rest* item, Painter* painter, const PaintOptions& opt)
    2084              : {
    2085              :     TRACE_DRAW_ITEM;
    2086            0 :     if (item->shouldNotBeDrawn()) {
    2087            0 :         return;
    2088              :     }
    2089            0 :     const Rest::LayoutData* ldata = item->ldata();
    2090            0 :     painter->setPen(item->curColor(opt));
    2091            0 :     item->drawSymbol(ldata->sym, painter);
    2092              : }
    2093              : 
    2094            0 : void SingleDraw::draw(const ShadowNote* item, Painter* painter, const PaintOptions&)
    2095              : {
    2096              :     TRACE_DRAW_ITEM;
    2097              : 
    2098            0 :     if (!item->visible() || !item->isValid()) {
    2099            0 :         return;
    2100              :     }
    2101              : 
    2102            0 :     PointF ap(item->pagePos());
    2103            0 :     painter->translate(ap);
    2104            0 :     double lw = item->style().styleAbsolute(Sid::stemWidth) * item->mag();
    2105            0 :     Pen pen(item->color(), lw, PenStyle::SolidLine, PenCapStyle::FlatCap);
    2106            0 :     painter->setPen(pen);
    2107              : 
    2108            0 :     bool up = item->computeUp();
    2109              : 
    2110              :     // Draw the accidental
    2111            0 :     SymId acc = Accidental::subtype2symbol(item->accidentalType());
    2112            0 :     if (acc != SymId::noSym) {
    2113            0 :         PointF posAcc;
    2114            0 :         posAcc.rx() -= item->symWidth(acc) + item->style().styleAbsolute(Sid::accidentalNoteDistance) * item->mag();
    2115            0 :         item->drawSymbol(acc, painter, posAcc);
    2116              :     }
    2117              : 
    2118              :     // Draw the notehead
    2119            0 :     item->drawSymbol(item->noteheadSymbol(), painter);
    2120              : 
    2121              :     // Draw the dots
    2122            0 :     double sp = item->spatium();
    2123            0 :     double sp2 = sp / 2;
    2124            0 :     double noteheadWidth = item->symWidth(item->noteheadSymbol());
    2125              : 
    2126            0 :     PointF posDot;
    2127            0 :     if (item->duration().dots() > 0) {
    2128            0 :         double d  = item->style().styleAbsolute(Sid::dotNoteDistance) * item->mag();
    2129            0 :         double dd = item->style().styleAbsolute(Sid::dotDotDistance) * item->mag();
    2130            0 :         posDot.rx() += (noteheadWidth + d);
    2131              : 
    2132            0 :         if (item->isRest()) {
    2133            0 :             posDot.ry() += Rest::getDotline(item->duration().type()) * sp2;
    2134              :         } else {
    2135            0 :             posDot.ry() -= (item->lineIndex() % 2 == 0 ? sp2 : 0);
    2136              :         }
    2137              : 
    2138            0 :         if (item->hasFlag() && up) {
    2139            0 :             posDot.rx() = std::max(posDot.x(), noteheadWidth + item->symBbox(item->flagSym()).right());
    2140              :         }
    2141              : 
    2142            0 :         for (int i = 0; i < item->duration().dots(); i++) {
    2143            0 :             posDot.rx() += dd * i;
    2144            0 :             item->drawSymbol(SymId::augmentationDot, painter, posDot);
    2145            0 :             posDot.rx() -= dd * i;
    2146              :         }
    2147              :     }
    2148              : 
    2149              :     // Draw stem and flag
    2150            0 :     if (item->hasStem()) {
    2151            0 :         double x = up ? (noteheadWidth - (lw / 2)) : lw / 2;
    2152            0 :         double y1 = item->symSmuflAnchor(item->noteheadSymbol(), up ? SmuflAnchorId::stemUpSE : SmuflAnchorId::stemDownNW).y();
    2153            0 :         double y2 = (up ? -3.5 : 3.5) * sp;
    2154              : 
    2155            0 :         if (item->hasFlag()) {
    2156            0 :             SymId flag = item->flagSym();
    2157            0 :             item->drawSymbol(flag, painter, PointF(x - (lw / 2), y2));
    2158            0 :             y2 += item->symSmuflAnchor(flag, up ? SmuflAnchorId::stemUpNW : SmuflAnchorId::stemDownSW).y();
    2159              :         }
    2160            0 :         painter->drawLine(LineF(x, y1, x, y2));
    2161              :     }
    2162              : 
    2163              :     // Draw ledger lines if needed
    2164            0 :     if (item->ledgerLinesVisible()) {
    2165            0 :         double extraLen = item->style().styleS(Sid::ledgerLineLength).val() * sp;
    2166            0 :         double x1 = -extraLen;
    2167            0 :         double x2 = noteheadWidth + extraLen;
    2168            0 :         double yOffset = item->staffOffsetY();
    2169            0 :         double step = sp2 * item->staffType()->lineDistance().val();
    2170              : 
    2171            0 :         lw = item->style().styleAbsolute(Sid::ledgerLineWidth) * item->mag();
    2172            0 :         pen.setWidthF(lw);
    2173            0 :         painter->setPen(pen);
    2174              : 
    2175            0 :         const int topLine = -2 + yOffset / step;
    2176            0 :         for (int i = topLine; i >= item->lineIndex(); i -= 2) {
    2177            0 :             double y = step * (i - item->lineIndex());
    2178            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2179              :         }
    2180            0 :         int l = item->staffType()->lines() * 2 + yOffset / step; // first ledger line below staff
    2181            0 :         for (int i = l; i <= item->lineIndex(); i += 2) {
    2182            0 :             double y = step * (i - item->lineIndex());
    2183            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2184              :         }
    2185              :     }
    2186              : 
    2187            0 :     item->drawArticulations(painter);
    2188              : 
    2189            0 :     painter->translate(-ap);
    2190            0 : }
    2191              : 
    2192            0 : void SingleDraw::draw(const SlurSegment* item, Painter* painter, const PaintOptions& opt)
    2193              : {
    2194              :     TRACE_DRAW_ITEM;
    2195              : 
    2196            0 :     Pen pen(item->curColor(opt));
    2197            0 :     double mag = item->staff() ? item->staff()->staffMag(item->slur()->tick()) : 1.0;
    2198              : 
    2199              :     //Replace generic Qt dash patterns with improved equivalents to show true dots (keep in sync with tie.cpp)
    2200            0 :     std::vector<double> dotted     = { 0.01, 1.99 };   // tighter than Qt PenStyle::DotLine equivalent - would be { 0.01, 2.99 }
    2201            0 :     std::vector<double> dashed     = { 3.00, 3.00 };   // Compensating for caps. Qt default PenStyle::DashLine is { 4.0, 2.0 }
    2202            0 :     std::vector<double> wideDashed = { 5.00, 6.00 };
    2203              : 
    2204            0 :     switch (item->slurTie()->styleType()) {
    2205            0 :     case SlurStyleType::Solid:
    2206            0 :         painter->setBrush(Brush(pen.color()));
    2207            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    2208            0 :         pen.setJoinStyle(PenJoinStyle::RoundJoin);
    2209            0 :         pen.setWidthF(item->style().styleAbsolute(Sid::slurEndWidth) * mag);
    2210            0 :         break;
    2211            0 :     case SlurStyleType::Dotted:
    2212            0 :         painter->setBrush(BrushStyle::NoBrush);
    2213            0 :         pen.setCapStyle(PenCapStyle::RoundCap);           // round dots
    2214            0 :         pen.setDashPattern(dotted);
    2215            0 :         pen.setWidthF(item->style().styleAbsolute(Sid::slurDottedWidth) * mag);
    2216            0 :         break;
    2217            0 :     case SlurStyleType::Dashed:
    2218            0 :         painter->setBrush(BrushStyle::NoBrush);
    2219            0 :         pen.setDashPattern(dashed);
    2220            0 :         pen.setWidthF(item->style().styleAbsolute(Sid::slurDottedWidth) * mag);
    2221            0 :         break;
    2222            0 :     case SlurStyleType::WideDashed:
    2223            0 :         painter->setBrush(BrushStyle::NoBrush);
    2224            0 :         pen.setDashPattern(wideDashed);
    2225            0 :         pen.setWidthF(item->style().styleAbsolute(Sid::slurDottedWidth) * mag);
    2226            0 :         break;
    2227            0 :     case SlurStyleType::Undefined:
    2228            0 :         break;
    2229              :     }
    2230            0 :     painter->setPen(pen);
    2231            0 :     painter->drawPath(item->ldata()->path());
    2232            0 : }
    2233              : 
    2234            0 : void SingleDraw::draw(const Spacer* item, Painter* painter, const PaintOptions&)
    2235              : {
    2236              :     TRACE_DRAW_ITEM;
    2237              : 
    2238            0 :     auto conf = item->configuration();
    2239              : 
    2240            0 :     Pen pen(conf->fontPrimaryColor(), item->spatium() * 0.3);
    2241              : 
    2242            0 :     painter->setPen(pen);
    2243            0 :     painter->setBrush(BrushStyle::NoBrush);
    2244            0 :     painter->drawPath(item->ldata()->path);
    2245            0 : }
    2246              : 
    2247            0 : void SingleDraw::draw(const StaffLines* item, Painter* painter, const PaintOptions& opt)
    2248              : {
    2249              :     TRACE_DRAW_ITEM;
    2250            0 :     painter->setPen(Pen(item->curColor(opt), item->lw(), PenStyle::SolidLine, PenCapStyle::FlatCap));
    2251            0 :     painter->drawLines(item->lines());
    2252            0 : }
    2253              : 
    2254            0 : void SingleDraw::draw(const StaffState* item, Painter* painter, const PaintOptions&)
    2255              : {
    2256              :     TRACE_DRAW_ITEM;
    2257              : 
    2258            0 :     const StaffState::LayoutData* ldata = item->ldata();
    2259            0 :     auto conf = item->configuration();
    2260              : 
    2261            0 :     Pen pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2262            0 :             ldata->lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
    2263            0 :     painter->setPen(pen);
    2264            0 :     painter->setBrush(BrushStyle::NoBrush);
    2265            0 :     painter->drawPath(ldata->path);
    2266            0 : }
    2267              : 
    2268            0 : void SingleDraw::draw(const StaffText* item, Painter* painter, const PaintOptions& opt)
    2269              : {
    2270              :     TRACE_DRAW_ITEM;
    2271              : 
    2272            0 :     drawTextBase(item, painter, opt);
    2273              : 
    2274            0 :     if (item->hasSoundFlag()) {
    2275            0 :         draw(item->soundFlag(), painter, opt);
    2276              :     }
    2277            0 : }
    2278              : 
    2279            0 : void SingleDraw::draw(const StaveSharingLabel* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2280              : {
    2281              :     TRACE_DRAW_ITEM;
    2282              : 
    2283            0 :     drawTextBase(item, painter, opt);
    2284            0 : }
    2285              : 
    2286            0 : void SingleDraw::draw(const StaffTypeChange* item, Painter* painter, const PaintOptions&)
    2287              : {
    2288              :     TRACE_DRAW_ITEM;
    2289              : 
    2290            0 :     auto conf = item->configuration();
    2291              : 
    2292            0 :     double _spatium = item->style().spatium();
    2293            0 :     double h  = _spatium * 2.5;
    2294            0 :     double w  = _spatium * 2.5;
    2295            0 :     double lineDist = 0.35;           // line distance for the icon 'staff lines'
    2296              :     // draw icon rectangle
    2297            0 :     painter->setPen(Pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2298            0 :                         item->lw(), PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin));
    2299            0 :     painter->setBrush(BrushStyle::NoBrush);
    2300            0 :     painter->drawRect(0, 0, w, h);
    2301              : 
    2302              :     // draw icon contents
    2303            0 :     int lines = 5;
    2304            0 :     if (item->staffType()) {
    2305            0 :         if (item->staffType()->stemless()) {       // a single notehead represents a stemless staff
    2306            0 :             item->drawSymbol(SymId::noteheadBlack, painter, PointF(w * 0.5 - 0.33 * _spatium, h * 0.5), 0.5);
    2307              :         }
    2308            0 :         if (item->staffType()->invisible()) {      // no lines needed. It's done.
    2309            0 :             return;
    2310              :         }
    2311              :         // show up to 6 lines
    2312            0 :         lines = std::min(item->staffType()->lines(), 6);
    2313              :     }
    2314              :     // calculate starting point Y for the lines from half the icon height (2.5) so staff lines appear vertically centered
    2315            0 :     double startY = 1.25 - (lines - 1) * lineDist * 0.5;
    2316            0 :     painter->setPen(Pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2317            0 :                         2.5, PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin));
    2318            0 :     for (int i=0; i < lines; i++) {
    2319            0 :         int y = (startY + i * lineDist) * _spatium;
    2320            0 :         painter->drawLine(0, y, w, y);
    2321              :     }
    2322            0 : }
    2323              : 
    2324            0 : void SingleDraw::draw(const Symbol* item, Painter* painter, const PaintOptions& opt)
    2325              : {
    2326              :     TRACE_DRAW_ITEM;
    2327            0 :     if (!item->isNoteDot() || !item->staff()->isTabStaff(item->tick())) {
    2328            0 :         painter->setPen(item->curColor(opt));
    2329            0 :         if (item->scoreFont()) {
    2330            0 :             item->scoreFont()->draw(item->sym(), painter, item->magS(), PointF());
    2331              :         } else {
    2332            0 :             item->drawSymbol(item->sym(), painter);
    2333              :         }
    2334              :     }
    2335            0 : }
    2336              : 
    2337            0 : void SingleDraw::draw(const FSymbol* item, Painter* painter, const PaintOptions& opt)
    2338              : {
    2339              :     TRACE_DRAW_ITEM;
    2340              : 
    2341            0 :     painter->setFont(item->font());
    2342            0 :     painter->setPen(item->curColor(opt));
    2343            0 :     painter->drawText(PointF(0, 0), item->toString());
    2344            0 : }
    2345              : 
    2346            0 : void SingleDraw::draw(const SystemDivider* item, Painter* painter, const PaintOptions& opt)
    2347              : {
    2348            0 :     draw(static_cast<const Symbol*>(item), painter, opt);
    2349            0 : }
    2350              : 
    2351            0 : void SingleDraw::draw(const SystemText* item, Painter* painter, const PaintOptions& opt)
    2352              : {
    2353              :     TRACE_DRAW_ITEM;
    2354            0 :     drawTextBase(item, painter, opt);
    2355            0 : }
    2356              : 
    2357            0 : void SingleDraw::draw(const SoundFlag* item, Painter* painter, const PaintOptions&)
    2358              : {
    2359              :     TRACE_DRAW_ITEM;
    2360              : 
    2361            0 :     painter->setFont(item->iconFont());
    2362            0 :     painter->drawText(item->ldata()->bbox(), muse::draw::AlignCenter, muse::draw::TextDontClip, Char(item->iconCode()));
    2363            0 : }
    2364              : 
    2365            0 : void SingleDraw::draw(const Tapping* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2366              : {
    2367            0 :     drawTextBase(item->text(), painter, opt);
    2368            0 : }
    2369              : 
    2370            0 : void SingleDraw::draw(const TempoText* item, Painter* painter, const PaintOptions& opt)
    2371              : {
    2372              :     TRACE_DRAW_ITEM;
    2373            0 :     drawTextBase(item, painter, opt);
    2374            0 : }
    2375              : 
    2376            0 : void SingleDraw::draw(const Text* item, Painter* painter, const PaintOptions& opt)
    2377              : {
    2378              :     TRACE_DRAW_ITEM;
    2379            0 :     drawTextBase(item, painter, opt);
    2380            0 : }
    2381              : 
    2382            0 : void SingleDraw::draw(const TextLineSegment* item, Painter* painter, const PaintOptions& opt)
    2383              : {
    2384              :     TRACE_DRAW_ITEM;
    2385            0 :     drawTextLineBaseSegment(item, painter, opt);
    2386            0 : }
    2387              : 
    2388            0 : void SingleDraw::draw(const TieSegment* item, Painter* painter, const PaintOptions& opt)
    2389              : {
    2390              :     TRACE_DRAW_ITEM;
    2391              : 
    2392              :     // hide tie toward the second chord of a cross-measure value
    2393            0 :     if (item->tie()->endNote() && item->tie()->endNote()->chord()->crossMeasure() == CrossMeasure::SECOND) {
    2394            0 :         return;
    2395              :     }
    2396              : 
    2397            0 :     Pen pen(item->curColor(opt));
    2398            0 :     double mag = item->staff() ? item->staff()->staffMag(item->tie()->tick()) : 1.0;
    2399              : 
    2400              :     //Replace generic Qt dash patterns with improved equivalents to show true dots (keep in sync with slur.cpp)
    2401            0 :     std::vector<double> dotted     = { 0.01, 1.99 };   // tighter than Qt PenStyle::DotLine equivalent - would be { 0.01, 2.99 }
    2402            0 :     std::vector<double> dashed     = { 3.00, 3.00 };   // Compensating for caps. Qt default PenStyle::DashLine is { 4.0, 2.0 }
    2403            0 :     std::vector<double> wideDashed = { 5.00, 6.00 };
    2404              : 
    2405            0 :     switch (item->slurTie()->styleType()) {
    2406            0 :     case SlurStyleType::Solid:
    2407            0 :         painter->setBrush(Brush(pen.color()));
    2408            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    2409            0 :         pen.setJoinStyle(PenJoinStyle::RoundJoin);
    2410            0 :         pen.setWidthF(item->endWidth() * mag);
    2411            0 :         break;
    2412            0 :     case SlurStyleType::Dotted:
    2413            0 :         painter->setBrush(BrushStyle::NoBrush);
    2414            0 :         pen.setCapStyle(PenCapStyle::RoundCap);           // True dots
    2415            0 :         pen.setDashPattern(dotted);
    2416            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2417            0 :         break;
    2418            0 :     case SlurStyleType::Dashed:
    2419            0 :         painter->setBrush(BrushStyle::NoBrush);
    2420            0 :         pen.setDashPattern(dashed);
    2421            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2422            0 :         break;
    2423            0 :     case SlurStyleType::WideDashed:
    2424            0 :         painter->setBrush(BrushStyle::NoBrush);
    2425            0 :         pen.setDashPattern(wideDashed);
    2426            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2427            0 :         break;
    2428            0 :     case SlurStyleType::Undefined:
    2429            0 :         break;
    2430              :     }
    2431            0 :     painter->setPen(pen);
    2432            0 :     painter->drawPath(item->ldata()->path());
    2433            0 : }
    2434              : 
    2435            0 : void SingleDraw::draw(const TimeSig* item, Painter* painter, const PaintOptions& opt)
    2436              : {
    2437              :     TRACE_DRAW_ITEM;
    2438              : 
    2439            0 :     if (item->staff() && !const_cast<const Staff*>(item->staff())->staffType(item->tick())->genTimesig()) {
    2440            0 :         return;
    2441              :     }
    2442            0 :     painter->setPen(item->curColor(opt));
    2443              : 
    2444            0 :     const TimeSig::LayoutData* ldata = item->ldata();
    2445              : 
    2446            0 :     item->drawSymbols(ldata->ns, painter, ldata->pz, item->scale());
    2447            0 :     item->drawSymbols(ldata->ds, painter, ldata->pn, item->scale());
    2448              : 
    2449            0 :     if (item->largeParentheses()) {
    2450            0 :         item->drawSymbol(SymId::timeSigParensLeft,  painter, ldata->pointLargeLeftParen,  item->scale().width());
    2451            0 :         item->drawSymbol(SymId::timeSigParensRight, painter, ldata->pointLargeRightParen, item->scale().width());
    2452              :     }
    2453              : }
    2454              : 
    2455            0 : void SingleDraw::draw(const TremoloSingleChord* item, Painter* painter, const PaintOptions& opt)
    2456              : {
    2457              :     TRACE_DRAW_ITEM;
    2458              : 
    2459            0 :     const TremoloSingleChord::LayoutData* ldata = item->ldata();
    2460              : 
    2461            0 :     if (item->isBuzzRoll()) {
    2462            0 :         painter->setPen(item->curColor(opt));
    2463            0 :         item->drawSymbol(SymId::buzzRoll, painter);
    2464              :     } else {
    2465            0 :         painter->setBrush(Brush(item->curColor(opt)));
    2466            0 :         painter->setNoPen();
    2467            0 :         painter->drawPath(item->path());
    2468              :     }
    2469              : 
    2470              :     // vertical line (stem)
    2471              :     {
    2472            0 :         double x = 0.0;     // bbox().width() * .25;
    2473            0 :         Pen pen(item->curColor(opt), item->absoluteFromSpatium(item->style().styleS(Sid::stemWidth)));
    2474            0 :         painter->setPen(pen);
    2475            0 :         const double sp = item->spatium();
    2476            0 :         if (item->isBuzzRoll()) {
    2477            0 :             painter->drawLine(LineF(x, -sp, x, ldata->bbox().bottom() + sp));
    2478              :         } else {
    2479            0 :             painter->drawLine(LineF(x, -sp * .5, x, item->path().boundingRect().height() + sp));
    2480              :         }
    2481            0 :     }
    2482            0 : }
    2483              : 
    2484            0 : void SingleDraw::draw(const TremoloTwoChord* item, Painter* painter, const PaintOptions& opt)
    2485              : {
    2486              :     TRACE_DRAW_ITEM;
    2487              : 
    2488            0 :     painter->setBrush(Brush(item->curColor(opt)));
    2489            0 :     painter->setNoPen();
    2490            0 :     painter->drawPath(item->path());
    2491            0 : }
    2492              : 
    2493            0 : void SingleDraw::draw(const TremoloBar* item, Painter* painter, const PaintOptions& opt)
    2494              : {
    2495              :     TRACE_DRAW_ITEM;
    2496            0 :     const TremoloBar::LayoutData* ldata = item->ldata();
    2497            0 :     const double lw = item->absoluteFromSpatium(item->lineWidth());
    2498            0 :     Pen pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
    2499            0 :     painter->setPen(pen);
    2500            0 :     painter->drawPolyline(ldata->polygon);
    2501            0 : }
    2502              : 
    2503            0 : void SingleDraw::draw(const TrillSegment* item, Painter* painter, const PaintOptions& opt)
    2504              : {
    2505              :     TRACE_DRAW_ITEM;
    2506            0 :     painter->setPen(item->spanner()->curColor(opt));
    2507            0 :     item->drawSymbols(item->symbols(), painter);
    2508            0 : }
    2509              : 
    2510            0 : void SingleDraw::draw(const TripletFeel* item, Painter* painter, const PaintOptions& opt)
    2511              : {
    2512              :     TRACE_DRAW_ITEM;
    2513            0 :     drawTextBase(item, painter, opt);
    2514            0 : }
    2515              : 
    2516            0 : void SingleDraw::draw(const Tuplet* item, Painter* painter, const PaintOptions& opt)
    2517              : {
    2518              :     TRACE_DRAW_ITEM;
    2519              : 
    2520              :     // if in a TAB without stems, tuplets are not shown
    2521            0 :     const StaffType* stt = item->staffType();
    2522            0 :     if (stt && stt->isTabStaff() && stt->stemless()) {
    2523            0 :         return;
    2524              :     }
    2525              : 
    2526            0 :     Color color(item->curColor(opt));
    2527            0 :     if (item->number()) {
    2528            0 :         painter->setPen(color);
    2529            0 :         PointF pos(item->number()->pos());
    2530            0 :         painter->translate(pos);
    2531            0 :         draw(item->number(), painter, opt);
    2532            0 :         painter->translate(-pos);
    2533              :     }
    2534            0 :     if (item->hasBracket()) {
    2535            0 :         painter->setPen(Pen(color, item->absoluteFromSpatium(item->bracketWidth()) * item->mag()));
    2536            0 :         if (!item->number()) {
    2537            0 :             painter->drawPolyline(item->bracketL, 4);
    2538              :         } else {
    2539            0 :             painter->drawPolyline(item->bracketL, 3);
    2540            0 :             painter->drawPolyline(item->bracketR, 3);
    2541              :         }
    2542              :     }
    2543              : }
    2544              : 
    2545            0 : void SingleDraw::draw(const VibratoSegment* item, Painter* painter, const PaintOptions& opt)
    2546              : {
    2547              :     TRACE_DRAW_ITEM;
    2548            0 :     painter->setPen(item->spanner()->curColor(opt));
    2549            0 :     item->drawSymbols(item->symbols(), painter);
    2550            0 : }
    2551              : 
    2552            0 : void SingleDraw::draw(const VoltaSegment* item, Painter* painter, const PaintOptions& opt)
    2553              : {
    2554              :     TRACE_DRAW_ITEM;
    2555            0 :     drawTextLineBaseSegment(item, painter, opt);
    2556            0 : }
    2557              : 
    2558            0 : void SingleDraw::draw(const WhammyBarSegment* item, Painter* painter, const PaintOptions& opt)
    2559              : {
    2560              :     TRACE_DRAW_ITEM;
    2561            0 :     drawTextLineBaseSegment(item, painter, opt);
    2562            0 : }
    2563              : 
    2564            0 : void SingleDraw::setMask(const EngravingItem* item, Painter* painter)
    2565              : {
    2566            0 :     const EngravingItem::LayoutData* ldata = item->ldata();
    2567              : 
    2568            0 :     const Shape& mask = ldata->mask();
    2569            0 :     if (mask.empty()) {
    2570            0 :         return;
    2571              :     }
    2572              : 
    2573            0 :     RectF background = ldata->bbox().padded(item->spatium());
    2574              : 
    2575            0 :     painter->setMask(background, mask.toRects());
    2576              : }
        

Generated by: LCOV version 2.0-1