LCOV - code coverage report
Current view: top level - src/engraving/rendering/score - tdraw.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 5.5 % 2097 115
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              : #include "tdraw.h"
      23              : 
      24              : #include "defer.h"
      25              : 
      26              : #include "draw/fontmetrics.h"
      27              : #include "draw/svgrenderer.h"
      28              : 
      29              : #include "iengravingconfiguration.h" // IWYU pragma: keep
      30              : #include "iengravingcontextconfiguration.h" // IWYU pragma: keep
      31              : 
      32              : #include "rendering/paintoptions.h"
      33              : #include "style/style.h"
      34              : #include "style/defaultstyle.h"
      35              : 
      36              : #include "dom/accidental.h"
      37              : #include "dom/actionicon.h"
      38              : #include "dom/ambitus.h"
      39              : #include "dom/arpeggio.h"
      40              : #include "dom/chordbracket.h"
      41              : #include "dom/articulation.h"
      42              : 
      43              : #include "dom/bagpembell.h"
      44              : #include "dom/barline.h"
      45              : #include "dom/beam.h"
      46              : #include "dom/bend.h"
      47              : #include "dom/box.h"
      48              : #include "dom/bracket.h"
      49              : #include "dom/breath.h"
      50              : 
      51              : #include "dom/chord.h"
      52              : #include "dom/chordline.h"
      53              : #include "dom/clef.h"
      54              : #include "dom/capo.h"
      55              : 
      56              : #include "dom/deadslapped.h"
      57              : #include "dom/dynamic.h"
      58              : 
      59              : #include "dom/expression.h"
      60              : 
      61              : #include "dom/fermata.h"
      62              : #include "dom/figuredbass.h"
      63              : #include "dom/fingering.h"
      64              : #include "dom/fret.h"
      65              : 
      66              : #include "dom/glissando.h"
      67              : #include "dom/gradualtempochange.h"
      68              : #include "dom/guitarbend.h"
      69              : 
      70              : #include "dom/hairpin.h"
      71              : #include "dom/hammeronpulloff.h"
      72              : #include "dom/harppedaldiagram.h"
      73              : #include "dom/harmonicmark.h"
      74              : #include "dom/harmony.h"
      75              : #include "dom/hook.h"
      76              : 
      77              : #include "dom/image.h"
      78              : #include "dom/instrchange.h"
      79              : #include "dom/instrumentname.h"
      80              : 
      81              : #include "dom/jump.h"
      82              : 
      83              : #include "dom/keysig.h"
      84              : 
      85              : #include "dom/laissezvib.h"
      86              : #include "dom/lasso.h"
      87              : #include "dom/layoutbreak.h"
      88              : #include "dom/ledgerline.h"
      89              : #include "dom/letring.h"
      90              : #include "dom/lyrics.h"
      91              : 
      92              : #include "dom/marker.h"
      93              : #include "dom/measurenumber.h"
      94              : #include "dom/measurerepeat.h"
      95              : #include "dom/mmrest.h"
      96              : #include "dom/mmrestrange.h"
      97              : 
      98              : #include "dom/note.h"
      99              : #include "dom/notedot.h"
     100              : #include "dom/noteline.h"
     101              : 
     102              : #include "dom/ornament.h"
     103              : #include "dom/ottava.h"
     104              : 
     105              : #include "dom/page.h"
     106              : #include "dom/pagelockindicator.h"
     107              : #include "dom/parenthesis.h"
     108              : #include "dom/partialtie.h"
     109              : #include "dom/palmmute.h"
     110              : #include "dom/part.h"
     111              : #include "dom/pedal.h"
     112              : #include "dom/pickscrape.h"
     113              : #include "dom/playcounttext.h"
     114              : #include "dom/playtechannotation.h"
     115              : 
     116              : #include "dom/rasgueado.h"
     117              : #include "dom/rehearsalmark.h"
     118              : #include "dom/rest.h"
     119              : 
     120              : #include "dom/score.h"
     121              : #include "dom/shadownote.h"
     122              : #include "dom/slur.h"
     123              : #include "dom/spacer.h"
     124              : #include "dom/staff.h"
     125              : #include "dom/stafflines.h"
     126              : #include "dom/staffstate.h"
     127              : #include "dom/stafftext.h"
     128              : #include "dom/stafftype.h"
     129              : #include "dom/stafftypechange.h"
     130              : #include "dom/staffvisibilityindicator.h"
     131              : #include "dom/stavesharinglabel.h"
     132              : #include "dom/stem.h"
     133              : #include "dom/stemslash.h"
     134              : #include "dom/sticking.h"
     135              : #include "dom/stringtunings.h"
     136              : #include "dom/symbol.h"
     137              : #include "dom/systemdivider.h"
     138              : #include "dom/systemlockindicator.h"
     139              : #include "dom/systemtext.h"
     140              : #include "dom/soundflag.h"
     141              : 
     142              : #include "dom/tabdurationsymbol.h"
     143              : #include "dom/tapping.h"
     144              : #include "dom/tempotext.h"
     145              : #include "dom/text.h"
     146              : #include "dom/textbase.h"
     147              : #include "dom/textline.h"
     148              : #include "dom/textlinebase.h"
     149              : #include "dom/tie.h"
     150              : #include "dom/timesig.h"
     151              : #include "dom/anchors.h"
     152              : #include "dom/tremolosinglechord.h"
     153              : #include "dom/tremolotwochord.h"
     154              : #include "dom/tremolobar.h"
     155              : #include "dom/trill.h"
     156              : #include "dom/tripletfeel.h"
     157              : #include "dom/tuplet.h"
     158              : 
     159              : #include "dom/vibrato.h"
     160              : #include "dom/volta.h"
     161              : 
     162              : #include "dom/whammybar.h"
     163              : 
     164              : #include "editing/mscoreview.h"
     165              : #include "editing/navigation.h"
     166              : 
     167              : #include "infrastructure/rtti.h"
     168              : 
     169              : #include "stemlayout.h"
     170              : 
     171              : // dev
     172              : #include "dom/system.h"
     173              : #include "dom/measure.h"
     174              : #include "dom/segment.h"
     175              : #include "dom/chord.h"
     176              : 
     177              : using namespace mu::engraving;
     178              : using namespace mu::engraving::rtti;
     179              : using namespace mu::engraving::rendering::score;
     180              : using namespace muse;
     181              : using namespace muse::draw;
     182              : 
     183          380 : void TDraw::drawItem(const EngravingItem* item, Painter* painter, const PaintOptions& opt)
     184              : {
     185          380 :     switch (item->type()) {
     186           94 :     case ElementType::ACCIDENTAL:   draw(item_cast<const Accidental*>(item), painter, opt);
     187           94 :         break;
     188            0 :     case ElementType::ACTION_ICON:  draw(item_cast<const ActionIcon*>(item), painter, opt);
     189            0 :         break;
     190            0 :     case ElementType::AMBITUS:      draw(item_cast<const Ambitus*>(item), painter, opt);
     191            0 :         break;
     192            0 :     case ElementType::ARPEGGIO:     draw(item_cast<const Arpeggio*>(item), painter, opt);
     193            0 :         break;
     194            0 :     case ElementType::CHORD_BRACKET: draw(item_cast<const ChordBracket*>(item), painter, opt);
     195            0 :         break;
     196            0 :     case ElementType::ARTICULATION: draw(item_cast<const Articulation*>(item), painter, opt);
     197            0 :         break;
     198              : 
     199            0 :     case ElementType::BAGPIPE_EMBELLISHMENT: draw(item_cast<const BagpipeEmbellishment*>(item), painter, opt);
     200            0 :         break;
     201           30 :     case ElementType::BAR_LINE:     draw(item_cast<const BarLine*>(item), painter, opt);
     202           30 :         break;
     203            0 :     case ElementType::BEAM:         draw(item_cast<const Beam*>(item), painter, opt);
     204            0 :         break;
     205            0 :     case ElementType::BEND:         draw(item_cast<const Bend*>(item), painter, opt);
     206            0 :         break;
     207            0 :     case ElementType::HBOX:         draw(item_cast<const HBox*>(item), painter, opt);
     208            0 :         break;
     209            0 :     case ElementType::VBOX:         draw(item_cast<const VBox*>(item), painter, opt);
     210            0 :         break;
     211            0 :     case ElementType::FBOX:         draw(item_cast<const FBox*>(item), painter, opt);
     212            0 :         break;
     213            0 :     case ElementType::TBOX:         draw(item_cast<const TBox*>(item), painter, opt);
     214            0 :         break;
     215            0 :     case ElementType::BRACKET:      draw(item_cast<const Bracket*>(item), painter, opt);
     216            0 :         break;
     217            0 :     case ElementType::BREATH:       draw(item_cast<const Breath*>(item), painter, opt);
     218            0 :         break;
     219              : 
     220            0 :     case ElementType::CHORDLINE:    draw(item_cast<const ChordLine*>(item), painter, opt);
     221            0 :         break;
     222           10 :     case ElementType::CLEF:         draw(item_cast<const Clef*>(item), painter, opt);
     223           10 :         break;
     224            0 :     case ElementType::CAPO:         draw(item_cast<const Capo*>(item), painter, opt);
     225            0 :         break;
     226              : 
     227            0 :     case ElementType::DEAD_SLAPPED: draw(item_cast<const DeadSlapped*>(item), painter, opt);
     228            0 :         break;
     229            0 :     case ElementType::DYNAMIC:      draw(item_cast<const Dynamic*>(item), painter, opt);
     230            0 :         break;
     231              : 
     232            0 :     case ElementType::EXPRESSION:   draw(item_cast<const Expression*>(item), painter, opt);
     233            0 :         break;
     234              : 
     235            0 :     case ElementType::FERMATA:      draw(item_cast<const Fermata*>(item), painter, opt);
     236            0 :         break;
     237            0 :     case ElementType::FIGURED_BASS: draw(item_cast<const FiguredBass*>(item), painter, opt);
     238            0 :         break;
     239            0 :     case ElementType::FINGERING:    draw(item_cast<const Fingering*>(item), painter, opt);
     240            0 :         break;
     241            0 :     case ElementType::FRET_DIAGRAM: draw(item_cast<const FretDiagram*>(item), painter, opt);
     242            0 :         break;
     243            0 :     case ElementType::FSYMBOL:      draw(item_cast<const FSymbol*>(item), painter, opt);
     244            0 :         break;
     245              : 
     246            0 :     case ElementType::GLISSANDO_SEGMENT: draw(item_cast<const GlissandoSegment*>(item), painter, opt);
     247            0 :         break;
     248            0 :     case ElementType::GRADUAL_TEMPO_CHANGE_SEGMENT: draw(item_cast<const GradualTempoChangeSegment*>(item), painter, opt);
     249            0 :         break;
     250            0 :     case ElementType::GUITAR_BEND_SEGMENT: draw(item_cast<const GuitarBendSegment*>(item), painter, opt);
     251            0 :         break;
     252            0 :     case ElementType::GUITAR_BEND_HOLD_SEGMENT: draw(item_cast<const GuitarBendHoldSegment*>(item), painter, opt);
     253            0 :         break;
     254            0 :     case ElementType::GUITAR_BEND_TEXT: drawTextBase(toTextBase(item), painter, opt);
     255            0 :         break;
     256              : 
     257            0 :     case ElementType::HAIRPIN_SEGMENT: draw(item_cast<const HairpinSegment*>(item), painter, opt);
     258            0 :         break;
     259            0 :     case ElementType::HAMMER_ON_PULL_OFF_SEGMENT: draw(item_cast<const HammerOnPullOffSegment*>(item), painter, opt);
     260            0 :         break;
     261            0 :     case ElementType::HAMMER_ON_PULL_OFF_TEXT: draw(item_cast<const HammerOnPullOffText*>(item), painter, opt);
     262            0 :         break;
     263            0 :     case ElementType::HARP_DIAGRAM: draw(item_cast<const HarpPedalDiagram*>(item), painter, opt);
     264            0 :         break;
     265            0 :     case ElementType::HARMONIC_MARK_SEGMENT: draw(item_cast<const HarmonicMarkSegment*>(item), painter, opt);
     266            0 :         break;
     267            0 :     case ElementType::HARMONY:      draw(item_cast<const Harmony*>(item), painter, opt);
     268            0 :         break;
     269            0 :     case ElementType::HOOK:         draw(item_cast<const Hook*>(item), painter, opt);
     270            0 :         break;
     271              : 
     272            0 :     case ElementType::IMAGE:        draw(item_cast<const Image*>(item), painter, opt);
     273            0 :         break;
     274            0 :     case ElementType::INSTRUMENT_CHANGE: draw(item_cast<const InstrumentChange*>(item), painter, opt);
     275            0 :         break;
     276            0 :     case ElementType::INSTRUMENT_NAME: draw(item_cast<const InstrumentName*>(item), painter, opt);
     277            0 :         break;
     278              : 
     279            0 :     case ElementType::JUMP:         draw(item_cast<const Jump*>(item), painter, opt);
     280            0 :         break;
     281              : 
     282            0 :     case ElementType::KEYSIG:       draw(item_cast<const KeySig*>(item), painter, opt);
     283            0 :         break;
     284            0 :     case ElementType::LAISSEZ_VIB_SEGMENT:  draw(item_cast<const LaissezVibSegment*>(item), painter, opt);
     285            0 :         break;
     286            0 :     case ElementType::LASSO:        draw(item_cast<const Lasso*>(item), painter, opt);
     287            0 :         break;
     288            0 :     case ElementType::LAYOUT_BREAK: draw(item_cast<const LayoutBreak*>(item), painter, opt);
     289            0 :         break;
     290           24 :     case ElementType::LEDGER_LINE:  draw(item_cast<const LedgerLine*>(item), painter, opt);
     291           24 :         break;
     292            0 :     case ElementType::LET_RING_SEGMENT: draw(item_cast<const LetRingSegment*>(item), painter, opt);
     293            0 :         break;
     294            0 :     case ElementType::LYRICS:       draw(item_cast<const Lyrics*>(item), painter, opt);
     295            0 :         break;
     296            0 :     case ElementType::LYRICSLINE_SEGMENT: draw(item_cast<const LyricsLineSegment*>(item), painter, opt);
     297            0 :         break;
     298            0 :     case ElementType::PARTIAL_LYRICSLINE_SEGMENT: draw(item_cast<const LyricsLineSegment*>(item), painter, opt);
     299            0 :         break;
     300              : 
     301            0 :     case ElementType::MARKER:       draw(item_cast<const Marker*>(item), painter, opt);
     302            0 :         break;
     303            0 :     case ElementType::MEASURE_NUMBER: draw(item_cast<const MeasureNumber*>(item), painter, opt);
     304            0 :         break;
     305            0 :     case ElementType::MEASURE_REPEAT: draw(item_cast<const MeasureRepeat*>(item), painter, opt);
     306            0 :         break;
     307            0 :     case ElementType::MMREST:       draw(item_cast<const MMRest*>(item), painter, opt);
     308            0 :         break;
     309            0 :     case ElementType::MMREST_RANGE: draw(item_cast<const MMRestRange*>(item), painter, opt);
     310            0 :         break;
     311              : 
     312          127 :     case ElementType::NOTE:         draw(item_cast<const Note*>(item), painter, opt);
     313          127 :         break;
     314            0 :     case ElementType::NOTEDOT:      draw(item_cast<const NoteDot*>(item), painter, opt);
     315            0 :         break;
     316            0 :     case ElementType::NOTEHEAD:     draw(item_cast<const NoteHead*>(item), painter, opt);
     317            0 :         break;
     318            0 :     case ElementType::NOTELINE_SEGMENT: draw(item_cast<const NoteLineSegment*>(item), painter, opt);
     319            0 :         break;
     320              : 
     321            0 :     case ElementType::ORNAMENT:     draw(item_cast<const Ornament*>(item), painter, opt);
     322            0 :         break;
     323            0 :     case ElementType::OTTAVA_SEGMENT:       draw(item_cast<const OttavaSegment*>(item), painter, opt);
     324            0 :         break;
     325            0 :     case ElementType::PAGE_LOCK_INDICATOR: draw(item_cast<const PageLockIndicator*>(item), painter, opt);
     326            0 :         break;
     327            0 :     case ElementType::PARENTHESIS:          draw(item_cast<const Parenthesis*>(item), painter, opt);
     328            0 :         break;
     329            0 :     case ElementType::PARTIAL_TIE_SEGMENT:  draw(item_cast<const PartialTieSegment*>(item), painter, opt);
     330            0 :         break;
     331            0 :     case ElementType::PALM_MUTE_SEGMENT:    draw(item_cast<const PalmMuteSegment*>(item), painter, opt);
     332            0 :         break;
     333            0 :     case ElementType::PEDAL_SEGMENT:        draw(item_cast<const PedalSegment*>(item), painter, opt);
     334            0 :         break;
     335            0 :     case ElementType::PICK_SCRAPE_SEGMENT:  draw(item_cast<const PickScrapeSegment*>(item), painter, opt);
     336            0 :         break;
     337            0 :     case ElementType::PLAY_COUNT_TEXT:      draw(item_cast<const PlayCountText*>(item), painter, opt);
     338            0 :         break;
     339            0 :     case ElementType::PLAYTECH_ANNOTATION:  draw(item_cast<const PlayTechAnnotation*>(item), painter, opt);
     340            0 :         break;
     341              : 
     342            0 :     case ElementType::RASGUEADO_SEGMENT:    draw(item_cast<const RasgueadoSegment*>(item), painter, opt);
     343            0 :         break;
     344            0 :     case ElementType::REHEARSAL_MARK:       draw(item_cast<const RehearsalMark*>(item), painter, opt);
     345            0 :         break;
     346            0 :     case ElementType::REST:                 draw(item_cast<const Rest*>(item), painter, opt);
     347            0 :         break;
     348              : 
     349            0 :     case ElementType::SHADOW_NOTE:          draw(item_cast<const ShadowNote*>(item), painter, opt);
     350            0 :         break;
     351            0 :     case ElementType::SLUR_SEGMENT:         draw(item_cast<const SlurSegment*>(item), painter, opt);
     352            0 :         break;
     353            0 :     case ElementType::SPACER:               draw(item_cast<const Spacer*>(item), painter, opt);
     354            0 :         break;
     355           20 :     case ElementType::STAFF_LINES:          draw(item_cast<const StaffLines*>(item), painter, opt);
     356           20 :         break;
     357            0 :     case ElementType::STAFF_STATE:          draw(item_cast<const StaffState*>(item), painter, opt);
     358            0 :         break;
     359            0 :     case ElementType::STAFF_TEXT:           draw(item_cast<const StaffText*>(item), painter, opt);
     360            0 :         break;
     361            0 :     case ElementType::STAVE_SHARING_LABEL:  draw(item_cast<const StaveSharingLabel*>(item), painter, opt);
     362            0 :         break;
     363            0 :     case ElementType::STAFFTYPE_CHANGE:     draw(item_cast<const StaffTypeChange*>(item), painter, opt);
     364            0 :         break;
     365            0 :     case ElementType::STAFF_VISIBILITY_INDICATOR: draw(item_cast<const StaffVisibilityIndicator*>(item), painter, opt);
     366            0 :         break;
     367           60 :     case ElementType::STEM:                 draw(item_cast<const Stem*>(item), painter, opt);
     368           60 :         break;
     369            0 :     case ElementType::STEM_SLASH:           draw(item_cast<const StemSlash*>(item), painter, opt);
     370            0 :         break;
     371            0 :     case ElementType::STICKING:             draw(item_cast<const Sticking*>(item), painter, opt);
     372            0 :         break;
     373            0 :     case ElementType::STRING_TUNINGS:       draw(item_cast<const StringTunings*>(item), painter, opt);
     374            0 :         break;
     375            0 :     case ElementType::SYMBOL:               draw(item_cast<const Symbol*>(item), painter, opt);
     376            0 :         break;
     377            0 :     case ElementType::SYSTEM_DIVIDER:       draw(item_cast<const SystemDivider*>(item), painter, opt);
     378            0 :         break;
     379            0 :     case ElementType::SYSTEM_TEXT:          draw(item_cast<const SystemText*>(item), painter, opt);
     380            0 :         break;
     381            0 :     case ElementType::SYSTEM_LOCK_INDICATOR: draw(item_cast<const SystemLockIndicator*>(item), painter, opt);
     382            0 :         break;
     383            0 :     case ElementType::SOUND_FLAG:           draw(item_cast<const SoundFlag*>(item), painter, opt);
     384            0 :         break;
     385              : 
     386            0 :     case ElementType::TAB_DURATION_SYMBOL:  draw(item_cast<const TabDurationSymbol*>(item), painter, opt);
     387            0 :         break;
     388            0 :     case ElementType::TAPPING:              draw(toTapping(item), painter, opt);
     389            0 :         break;
     390            0 :     case ElementType::TAPPING_HALF_SLUR_SEGMENT: draw(toSlurSegment(item), painter, opt);
     391            0 :         break;
     392            0 :     case ElementType::TEMPO_TEXT:           draw(item_cast<const TempoText*>(item), painter, opt);
     393            0 :         break;
     394            0 :     case ElementType::TEXT:                 draw(item_cast<const Text*>(item), painter, opt);
     395            0 :         break;
     396            0 :     case ElementType::TEXTLINE_SEGMENT:     draw(item_cast<const TextLineSegment*>(item), painter, opt);
     397            0 :         break;
     398            0 :     case ElementType::TIE_SEGMENT:          draw(item_cast<const TieSegment*>(item), painter, opt);
     399            0 :         break;
     400           10 :     case ElementType::TIMESIG:              draw(item_cast<const TimeSig*>(item), painter, opt);
     401           10 :         break;
     402            0 :     case ElementType::TIME_TICK_ANCHOR:     draw(item_cast<const TimeTickAnchor*>(item), painter, opt);
     403            0 :         break;
     404            0 :     case ElementType::TREMOLO_SINGLECHORD:  draw(item_cast<const TremoloSingleChord*>(item), painter, opt);
     405            0 :         break;
     406            0 :     case ElementType::TREMOLO_TWOCHORD:     draw(item_cast<const TremoloTwoChord*>(item), painter, opt);
     407            0 :         break;
     408            0 :     case ElementType::TREMOLOBAR:           draw(item_cast<const TremoloBar*>(item), painter, opt);
     409            0 :         break;
     410            0 :     case ElementType::TRILL_SEGMENT:        draw(item_cast<const TrillSegment*>(item), painter, opt);
     411            0 :         break;
     412            0 :     case ElementType::TRIPLET_FEEL:         draw(item_cast<const TripletFeel*>(item), painter, opt);
     413            0 :         break;
     414            0 :     case ElementType::TUPLET:               draw(item_cast<const Tuplet*>(item), painter, opt);
     415            0 :         break;
     416              : 
     417            0 :     case ElementType::VIBRATO_SEGMENT:      draw(item_cast<const VibratoSegment*>(item), painter, opt);
     418            0 :         break;
     419            0 :     case ElementType::VOLTA_SEGMENT:        draw(item_cast<const VoltaSegment*>(item), painter, opt);
     420            0 :         break;
     421              : 
     422            0 :     case ElementType::WHAMMY_BAR_SEGMENT:   draw(item_cast<const WhammyBarSegment*>(item), painter, opt);
     423            0 :         break;
     424              : 
     425            5 :     case ElementType::PAGE:
     426              :     case ElementType::SYSTEM:
     427              :     case ElementType::MEASURE:
     428              :     case ElementType::SEGMENT:
     429              :     case ElementType::CHORD:
     430              :     case ElementType::GRACE_NOTES_GROUP:
     431            5 :         break;
     432              : 
     433            0 :     default:
     434            0 :         NOT_IMPLEMENTED << " type: " << item->typeName();
     435            0 :         UNREACHABLE;
     436              :     }
     437          380 : }
     438              : 
     439           94 : void TDraw::draw(const Accidental* item, Painter* painter, const PaintOptions& opt)
     440              : {
     441              :     TRACE_DRAW_ITEM;
     442           94 :     IF_ASSERT_FAILED(item->ldata()) {
     443            0 :         return;
     444              :     }
     445              : 
     446           94 :     painter->setPen(item->curColor(opt));
     447          188 :     for (const Accidental::LayoutData::Sym& e : item->ldata()->syms) {
     448           94 :         item->drawSymbol(e.sym, painter, PointF(e.x, e.y));
     449              :     }
     450              : }
     451              : 
     452            0 : void TDraw::draw(const ActionIcon* item, Painter* painter, const PaintOptions&)
     453              : {
     454              :     TRACE_DRAW_ITEM;
     455            0 :     const ActionIcon::LayoutData* ldata = item->ldata();
     456            0 :     painter->setFont(item->iconFont());
     457            0 :     painter->drawText(ldata->bbox(), muse::draw::AlignCenter, muse::draw::TextDontClip, Char(item->icon()));
     458            0 : }
     459              : 
     460            0 : void TDraw::draw(const Ambitus* item, Painter* painter, const PaintOptions& opt)
     461              : {
     462              :     TRACE_DRAW_ITEM;
     463              : 
     464            0 :     const Ambitus::LayoutData* ldata = item->ldata();
     465            0 :     IF_ASSERT_FAILED(ldata) {
     466            0 :         return;
     467              :     }
     468              : 
     469            0 :     double spatium = item->spatium();
     470            0 :     double lw = item->lineWidth().val() * spatium;
     471            0 :     painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     472              : 
     473            0 :     item->drawSymbol(item->noteHead(), painter, ldata->topPos);
     474            0 :     item->drawSymbol(item->noteHead(), painter, ldata->bottomPos);
     475            0 :     if (item->hasLine()) {
     476            0 :         painter->drawLine(ldata->line);
     477              :     }
     478              : 
     479              :     // draw ledger lines (if not in a palette)
     480            0 :     if (item->segment() && item->track() != muse::nidx) {
     481            0 :         Fraction tick = item->segment()->tick();
     482            0 :         Staff* staff = item->score()->staff(item->staffIdx());
     483            0 :         double lineDist = staff->lineDistance(tick);
     484            0 :         int numOfLines = staff->lines(tick);
     485            0 :         double step = lineDist * spatium;
     486            0 :         double stepTolerance = step * 0.1;
     487            0 :         double ledgerLineLength = item->style().styleS(Sid::ledgerLineLength).val() * spatium;
     488            0 :         double ledgerLineWidth = item->style().styleS(Sid::ledgerLineWidth).val() * spatium;
     489            0 :         painter->setPen(Pen(item->curColor(opt), ledgerLineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
     490              : 
     491            0 :         if (ldata->topPos.y() - stepTolerance <= -step) {
     492            0 :             double xMin = ldata->topPos.x() - ledgerLineLength;
     493            0 :             double xMax = ldata->topPos.x() + item->headWidth() + ledgerLineLength;
     494            0 :             for (double y = -step; y >= ldata->topPos.y() - stepTolerance; y -= step) {
     495            0 :                 painter->drawLine(PointF(xMin, y), PointF(xMax, y));
     496              :             }
     497              :         }
     498              : 
     499            0 :         if (ldata->bottomPos.y() + stepTolerance >= numOfLines * step) {
     500            0 :             double xMin = ldata->bottomPos.x() - ledgerLineLength;
     501            0 :             double xMax = ldata->bottomPos.x() + item->headWidth() + ledgerLineLength;
     502            0 :             for (double y = numOfLines * step; y <= ldata->bottomPos.y() + stepTolerance; y += step) {
     503            0 :                 painter->drawLine(PointF(xMin, y), PointF(xMax, y));
     504              :             }
     505              :         }
     506              :     }
     507              : }
     508              : 
     509            0 : void TDraw::draw(const Arpeggio* item, Painter* painter, const PaintOptions& opt)
     510              : {
     511              :     TRACE_DRAW_ITEM;
     512              : 
     513            0 :     const Arpeggio::LayoutData* ldata = item->ldata();
     514            0 :     IF_ASSERT_FAILED(ldata) {
     515            0 :         return;
     516              :     }
     517              : 
     518            0 :     const double y1 = ldata->bbox().top();
     519            0 :     const double y2 = ldata->bbox().bottom();
     520            0 :     const double lineWidth = item->style().styleAbsolute(Sid::arpeggioLineWidth);
     521              : 
     522            0 :     painter->setPen(Pen(item->curColor(opt), lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
     523            0 :     painter->save();
     524              : 
     525            0 :     switch (item->arpeggioType()) {
     526            0 :     case ArpeggioType::NORMAL:
     527              :     case ArpeggioType::UP:
     528              :     {
     529            0 :         const RectF& r = ldata->symsBBox;
     530            0 :         painter->rotate(-90.0);
     531            0 :         item->drawSymbols(ldata->symbols, painter, PointF(-r.right() - y1, -r.bottom() + r.height()));
     532            0 :     } break;
     533              : 
     534            0 :     case ArpeggioType::DOWN:
     535              :     {
     536            0 :         const RectF& r = ldata->symsBBox;
     537            0 :         painter->rotate(90.0);
     538            0 :         item->drawSymbols(ldata->symbols, painter, PointF(-r.left() + y1, -r.top() - r.height()));
     539            0 :     } break;
     540              : 
     541            0 :     case ArpeggioType::UP_STRAIGHT:
     542              :     {
     543            0 :         const RectF& r = ldata->symsBBox;
     544            0 :         double x1 = item->spatium() * 0.5;
     545            0 :         item->drawSymbol(SymId::arrowheadBlackUp, painter, PointF(x1 - r.width() * 0.5, y1 - r.top()));
     546            0 :         double ny1 = y1 - r.top() * 0.5;
     547            0 :         painter->drawLine(LineF(x1, ny1, x1, y2));
     548            0 :     } break;
     549              : 
     550            0 :     case ArpeggioType::DOWN_STRAIGHT:
     551              :     {
     552            0 :         const RectF& r = ldata->symsBBox;
     553            0 :         double x1 = item->spatium() * 0.5;
     554            0 :         item->drawSymbol(SymId::arrowheadBlackDown, painter, PointF(x1 - r.width() * 0.5, y2 - r.bottom()));
     555            0 :         double ny2 = y2 + r.top() * 0.5;
     556            0 :         painter->drawLine(LineF(x1, y1, x1, ny2));
     557            0 :     } break;
     558              : 
     559            0 :     case ArpeggioType::BRACKET:
     560              :     {
     561            0 :         double w = item->style().styleS(Sid::arpeggioHookLen).val() * item->spatium();
     562            0 :         painter->drawLine(LineF(0.0, y1, w, y1));
     563            0 :         painter->drawLine(LineF(0.0, y2, w, y2));
     564            0 :         painter->drawLine(LineF(0.0, y1 - lineWidth / 2, 0.0, y2 + lineWidth / 2));
     565            0 :     } break;
     566              :     }
     567            0 :     painter->restore();
     568              : }
     569              : 
     570            0 : void TDraw::draw(const ChordBracket* item, muse::draw::Painter* painter, const PaintOptions& opt)
     571              : {
     572            0 :     const Arpeggio::LayoutData* ldata = item->ldata();
     573              : 
     574            0 :     const double lineWidth = item->style().styleAbsolute(Sid::chordBracketLineWidth);
     575            0 :     painter->setPen(Pen(item->curColor(opt), lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
     576              : 
     577            0 :     const double halfLineWidth = 0.5 * lineWidth;
     578            0 :     const double y1 = ldata->bbox().top() + halfLineWidth;
     579            0 :     const double y2 = ldata->bbox().bottom() - halfLineWidth;
     580              : 
     581            0 :     double w = item->absoluteFromSpatium(item->hookLength());
     582              : 
     583            0 :     if (item->hookPos() != DirectionV::DOWN) {
     584            0 :         painter->drawLine(LineF(0.0, y1, w, y1));
     585              :     }
     586            0 :     if (item->hookPos() != DirectionV::UP) {
     587            0 :         painter->drawLine(LineF(0.0, y2, w, y2));
     588              :     }
     589              : 
     590            0 :     const double x = item->rightSide() ? w - halfLineWidth : halfLineWidth;
     591            0 :     painter->drawLine(LineF(x, y1, x, y2));
     592            0 : }
     593              : 
     594            0 : void TDraw::draw(const Articulation* item, Painter* painter, const PaintOptions& opt)
     595              : {
     596              :     TRACE_DRAW_ITEM;
     597              : 
     598            0 :     painter->setPen(item->curColor(opt));
     599              : 
     600            0 :     if (item->textType() == ArticulationTextType::NO_TEXT) {
     601            0 :         item->drawSymbol(item->symId(), painter);
     602              :     } else {
     603            0 :         drawTextBase(item->text(), painter, opt);
     604              :     }
     605            0 : }
     606              : 
     607            0 : void TDraw::draw(const Ornament* item, Painter* painter, const PaintOptions& opt)
     608              : {
     609            0 :     draw(static_cast<const Articulation*>(item), painter, opt);
     610            0 : }
     611              : 
     612            0 : void TDraw::draw(const BagpipeEmbellishment* item, Painter* painter, const PaintOptions& opt)
     613              : {
     614              :     TRACE_DRAW_ITEM;
     615              : 
     616            0 :     const BagpipeEmbellishment::LayoutData* data = item->ldata();
     617            0 :     IF_ASSERT_FAILED(data) {
     618            0 :         return;
     619              :     }
     620            0 :     const BagpipeEmbellishment::LayoutData::BeamData& dataBeam = data->beamData;
     621              : 
     622            0 :     Pen pen(item->curColor(opt), data->stemLineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
     623            0 :     painter->setPen(pen);
     624              : 
     625              :     // draw the notes including stem, (optional) flag and (optional) ledger line
     626            0 :     for (const auto& p : data->notesData) {
     627            0 :         const BagpipeEmbellishment::LayoutData::NoteData& noteData = p.second;
     628              : 
     629              :         // Draw Grace Note
     630              :         {
     631              :             // draw head
     632            0 :             item->drawSymbol(data->headsym, painter, noteData.headXY);
     633              : 
     634              :             // draw stem
     635            0 :             painter->drawLine(noteData.stemLine);
     636              : 
     637            0 :             if (data->isDrawFlag) {
     638              :                 // draw flag
     639            0 :                 item->drawSymbol(data->flagsym, painter, noteData.flagXY);
     640              :             }
     641              :         }
     642              : 
     643              :         // draw the ledger line for high A
     644            0 :         if (!noteData.ledgerLine.isNull()) {
     645            0 :             painter->drawLine(noteData.ledgerLine);
     646              :         }
     647              :     }
     648              : 
     649            0 :     if (data->isDrawBeam) {
     650            0 :         Pen beamPen(item->curColor(opt), dataBeam.width, PenStyle::SolidLine, PenCapStyle::FlatCap);
     651            0 :         painter->setPen(beamPen);
     652              :         // draw the beams
     653            0 :         auto drawBeams = [](Painter* painter, const double spatium,
     654              :                             const double x1, const double x2, double y)
     655              :         {
     656              :             // draw the beams
     657            0 :             painter->drawLine(LineF(x1, y, x2, y));
     658            0 :             y += spatium / 1.5;
     659            0 :             painter->drawLine(LineF(x1, y, x2, y));
     660            0 :             y += spatium / 1.5;
     661            0 :             painter->drawLine(LineF(x1, y, x2, y));
     662            0 :         };
     663              : 
     664            0 :         drawBeams(painter, data->spatium, dataBeam.x1, dataBeam.x2, dataBeam.y);
     665            0 :     }
     666            0 : }
     667              : 
     668            0 : static void drawDots(const BarLine* item, Painter* painter, double x)
     669              : {
     670            0 :     double spatium = item->spatium();
     671              : 
     672              :     double y1l;
     673              :     double y2l;
     674            0 :     if (item->ownershipParent() == 0) {      // for use in palette (always Bravura)
     675              :         //Bravura shifted repeatDot symbol 0.5sp upper in the font itself (1.272)
     676            0 :         y1l = 1.5 * spatium;
     677            0 :         y2l = 2.5 * spatium;
     678              :     } else {
     679            0 :         const StaffType* st = item->staffType();
     680            0 :         const int lines = st->lines();
     681            0 :         const double lineDistance = item->absoluteFromSpatium(st->lineDistance());
     682              : 
     683            0 :         y1l = (static_cast<double>((lines - 1) / 2) - 0.5) * lineDistance;
     684            0 :         y2l = (static_cast<double>(lines / 2) + 0.5) * lineDistance;
     685              : 
     686              :         //adjust for staffType offset
     687            0 :         double stYOffset = item->staffOffsetY();
     688            0 :         y1l += stYOffset;
     689            0 :         y2l += stYOffset;
     690              :     }
     691              : 
     692            0 :     item->drawSymbol(SymId::repeatDot, painter, PointF(x, y1l));
     693            0 :     item->drawSymbol(SymId::repeatDot, painter, PointF(x, y2l));
     694            0 : }
     695              : 
     696            0 : static void drawTips(const BarLine* item, const BarLine::LayoutData* data, Painter* painter, bool reversed, double x)
     697              : {
     698            0 :     if (reversed) {
     699            0 :         if (item->isTop()) {
     700            0 :             item->drawSymbol(SymId::reversedBracketTop, painter, PointF(x - item->symWidth(SymId::reversedBracketTop), data->y1));
     701              :         }
     702            0 :         if (item->isBottom()) {
     703            0 :             item->drawSymbol(SymId::reversedBracketBottom, painter, PointF(x - item->symWidth(SymId::reversedBracketBottom), data->y2));
     704              :         }
     705              :     } else {
     706            0 :         if (item->isTop()) {
     707            0 :             item->drawSymbol(SymId::bracketTop, painter, PointF(x, data->y1));
     708              :         }
     709            0 :         if (item->isBottom()) {
     710            0 :             item->drawSymbol(SymId::bracketBottom, painter, PointF(x, data->y2));
     711              :         }
     712              :     }
     713            0 : }
     714              : 
     715           30 : void TDraw::draw(const BarLine* item, Painter* painter, const PaintOptions& opt)
     716              : {
     717              :     TRACE_DRAW_ITEM;
     718              : 
     719           30 :     const BarLine::LayoutData* data = item->ldata();
     720           30 :     IF_ASSERT_FAILED(data) {
     721           30 :         return;
     722              :     }
     723              : 
     724           30 :     painter->save();
     725           30 :     DEFER {
     726           30 :         painter->restore();
     727           30 :     };
     728              : 
     729           30 :     setMask(item, painter);
     730              : 
     731           30 :     switch (item->barLineType()) {
     732           20 :     case BarLineType::NORMAL: {
     733           20 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     734           20 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     735           20 :         painter->drawLine(LineF(lw * .5, data->y1, lw * .5, data->y2));
     736              :     }
     737           20 :     break;
     738              : 
     739            0 :     case BarLineType::BROKEN: {
     740            0 :         double lw = item->style().styleAbsolute(Sid::dashBarWidth) * item->mag();
     741            0 :         double dl = RealIsNull(lw) ? 0.0 : item->style().styleAbsolute(Sid::dashBarDash) * item->mag() / lw;
     742            0 :         double gl = RealIsNull(lw) ? 0.0 : item->style().styleAbsolute(Sid::dashBarGap) * item->mag() / lw;
     743            0 :         Pen pen(item->curColor(opt), lw, PenStyle::DashLine, PenCapStyle::FlatCap);
     744            0 :         pen.setDashPattern({ dl, gl });
     745            0 :         painter->setPen(pen);
     746            0 :         painter->drawLine(LineF(lw * .5, data->y1, lw * .5, data->y2));
     747            0 :     }
     748            0 :     break;
     749              : 
     750            0 :     case BarLineType::DOTTED: {
     751            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     752            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::DotLine, PenCapStyle::FlatCap));
     753            0 :         painter->drawLine(LineF(lw * .5, data->y1, lw * .5, data->y2));
     754              :     }
     755            0 :     break;
     756              : 
     757           10 :     case BarLineType::END: {
     758           10 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     759           10 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     760           10 :         double x  = lw * .5;
     761           10 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     762              : 
     763           10 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     764           10 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     765           10 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     766           10 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     767              :     }
     768           10 :     break;
     769              : 
     770            0 :     case BarLineType::DOUBLE: {
     771            0 :         double lw = item->style().styleAbsolute(Sid::doubleBarWidth) * item->mag();
     772            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     773            0 :         double x = lw * .5;
     774            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     775            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::doubleBarDistance) + (lw * .5)) * item->mag();
     776            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     777              :     }
     778            0 :     break;
     779              : 
     780            0 :     case BarLineType::REVERSE_END: {
     781            0 :         double lw = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     782            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     783            0 :         double x = lw * .5;
     784            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     785              : 
     786            0 :         double lw2 = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     787            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     788            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     789            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     790              :     }
     791            0 :     break;
     792              : 
     793            0 :     case BarLineType::HEAVY: {
     794            0 :         double lw = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     795            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     796            0 :         painter->drawLine(LineF(lw * .5, data->y1, lw * .5, data->y2));
     797              :     }
     798            0 :     break;
     799              : 
     800            0 :     case BarLineType::DOUBLE_HEAVY: {
     801            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     802            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     803            0 :         double x = lw2 * .5;
     804            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     805            0 :         x += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     806            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     807              :     }
     808            0 :     break;
     809              : 
     810            0 :     case BarLineType::START_REPEAT: {
     811            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     812            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     813            0 :         double x = lw2 * .5;
     814            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     815              : 
     816            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     817            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     818            0 :         x += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw * .5)) * item->mag();
     819            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     820              : 
     821            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::repeatBarlineDotSeparation)) * item->mag();
     822            0 :         drawDots(item, painter, x);
     823              : 
     824            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     825            0 :             drawTips(item, data, painter, false, 0.0);
     826              :         }
     827              :     }
     828            0 :     break;
     829              : 
     830            0 :     case BarLineType::END_REPEAT: {
     831            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     832            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     833              : 
     834            0 :         double x = 0.0;
     835            0 :         drawDots(item, painter, x);
     836              : 
     837            0 :         x += item->symBbox(SymId::repeatDot).width();
     838            0 :         x += (item->style().styleAbsolute(Sid::repeatBarlineDotSeparation) + (lw * .5)) * item->mag();
     839            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     840              : 
     841            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     842            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     843            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     844            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     845              : 
     846            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     847            0 :             drawTips(item, data, painter, true, x + lw2 * .5);
     848              :         }
     849              :     }
     850            0 :     break;
     851            0 :     case BarLineType::END_START_REPEAT: {
     852            0 :         double lw = item->style().styleAbsolute(Sid::barWidth) * item->mag();
     853            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     854              : 
     855            0 :         double x = 0.0;
     856            0 :         drawDots(item, painter, x);
     857              : 
     858            0 :         x += item->symBbox(SymId::repeatDot).width();
     859            0 :         x += (item->style().styleAbsolute(Sid::repeatBarlineDotSeparation) + (lw * .5)) * item->mag();
     860            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     861              : 
     862            0 :         double lw2 = item->style().styleAbsolute(Sid::endBarWidth) * item->mag();
     863            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw2 * .5)) * item->mag();
     864            0 :         painter->setPen(Pen(item->curColor(opt), lw2, PenStyle::SolidLine, PenCapStyle::FlatCap));
     865            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     866              : 
     867            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     868            0 :             drawTips(item, data, painter, true, x + lw2 * .5);
     869              :         }
     870              : 
     871            0 :         painter->setPen(Pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::FlatCap));
     872            0 :         x  += ((lw2 * .5) + item->style().styleAbsolute(Sid::endBarDistance) + (lw * .5)) * item->mag();
     873            0 :         painter->drawLine(LineF(x, data->y1, x, data->y2));
     874              : 
     875            0 :         x += ((lw * .5) + item->style().styleAbsolute(Sid::repeatBarlineDotSeparation)) * item->mag();
     876            0 :         drawDots(item, painter, x);
     877              : 
     878            0 :         if (item->style().styleB(Sid::repeatBarTips)) {
     879            0 :             drawTips(item, data, painter, false, 0.0);
     880              :         }
     881              :     }
     882            0 :     break;
     883              :     }
     884              : 
     885              :     // draw irregular measure mark
     886              : 
     887           30 :     if (opt.isPrinting || !item->score()->markIrregularMeasures()) {
     888           30 :         return;
     889              :     }
     890              : 
     891            0 :     const Segment* s = item->segment();
     892            0 :     if (s && (s->isEndBarLineType() || s->isStartRepeatBarLineType())) {
     893            0 :         const Measure* measure = s->measure();
     894            0 :         if (s->isStartRepeatBarLineType()) {
     895            0 :             const Measure* prevMeasure = measure ? measure->prevMeasure() : nullptr;
     896            0 :             if (!prevMeasure) {
     897            0 :                 return;
     898              :             }
     899            0 :             if (const BarLine* prevEndBl = prevMeasure->endBarLine(item->staffIdx())) {
     900            0 :                 if (prevEndBl->segment() && prevEndBl->segment()->enabled()) {
     901            0 :                     return;
     902              :                 }
     903              :             }
     904            0 :             measure = prevMeasure;
     905              :         }
     906              : 
     907            0 :         if (measure && measure->isIrregular() && !measure->isMMRest()) {
     908            0 :             painter->setPen(item->configuration()->invisibleColor());
     909            0 :             Font f(u"Edwin", Font::Type::Text);
     910            0 :             f.setPointSizeF(12 * item->spatium() / item->defaultSpatium());
     911            0 :             f.setBold(true);
     912            0 :             Char ch = measure->ticks() > measure->timesig() ? u'+' : u'-';
     913            0 :             RectF r = FontMetrics(f).boundingRect(ch);
     914              : 
     915            0 :             painter->setFont(f);
     916            0 :             painter->drawText(-r.width(), -item->spatium(), ch);
     917            0 :         }
     918              :     }
     919           30 : }
     920              : 
     921            0 : void TDraw::draw(const Beam* item, Painter* painter, const PaintOptions& opt)
     922              : {
     923              :     TRACE_DRAW_ITEM;
     924            0 :     if (item->beamSegments().empty()) {
     925            0 :         return;
     926              :     }
     927            0 :     painter->setBrush(Brush(item->curColor(opt)));
     928            0 :     painter->setNoPen();
     929              : 
     930              :     // make beam thickness independent of slant
     931              :     // (expression can be simplified?)
     932              : 
     933            0 :     const LineF bs = item->beamSegments().front()->line;
     934            0 :     double d  = (std::abs(bs.y2() - bs.y1())) / (bs.x2() - bs.x1());
     935            0 :     if (item->beamSegments().size() > 1 && d > M_PI / 6.0) {
     936            0 :         d = M_PI / 6.0;
     937              :     }
     938            0 :     double ww = (item->beamWidth() / 2.0) / sin(M_PI_2 - atan(d));
     939              : 
     940            0 :     for (const BeamSegment* bs1 : item->beamSegments()) {
     941            0 :         painter->drawPolygon(
     942            0 :             PolygonF({
     943            0 :             PointF(bs1->line.x1(), bs1->line.y1() - ww),
     944            0 :             PointF(bs1->line.x2(), bs1->line.y2() - ww),
     945            0 :             PointF(bs1->line.x2(), bs1->line.y2() + ww),
     946            0 :             PointF(bs1->line.x1(), bs1->line.y1() + ww),
     947            0 :         }),
     948              :             FillRule::OddEvenFill);
     949              :     }
     950              : }
     951              : 
     952            0 : void TDraw::draw(const Bend* item, Painter* painter, const PaintOptions& opt)
     953              : {
     954              :     TRACE_DRAW_ITEM;
     955              : 
     956            0 :     const Bend::LayoutData* data = item->ldata();
     957            0 :     IF_ASSERT_FAILED(data) {
     958            0 :         return;
     959              :     }
     960              : 
     961            0 :     double spatium = item->spatium();
     962            0 :     double lw = item->absoluteFromSpatium(item->lineWidth());
     963              : 
     964            0 :     Pen pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
     965            0 :     painter->setPen(pen);
     966            0 :     painter->setBrush(Brush(item->curColor(opt)));
     967              : 
     968            0 :     Font f = item->font(spatium);
     969              : 
     970            0 :     double x  = data->noteWidth + spatium * .2;
     971            0 :     double y  = -spatium * .8;
     972              :     double x2, y2;
     973              : 
     974            0 :     double aw = item->style().styleAbsolute(Sid::bendArrowWidth);
     975            0 :     PolygonF arrowUp;
     976            0 :     arrowUp << PointF(0, 0) << PointF(aw * .5, aw) << PointF(-aw * .5, aw);
     977            0 :     PolygonF arrowDown;
     978            0 :     arrowDown << PointF(0, 0) << PointF(aw * .5, -aw) << PointF(-aw * .5, -aw);
     979              : 
     980            0 :     size_t n = item->points().size();
     981            0 :     for (size_t pt = 0; pt < n - 1; ++pt) {
     982            0 :         int pitch = item->points()[pt].pitch;
     983            0 :         if (pt == 0 && pitch) {
     984            0 :             y2 = -data->notePos.y() - spatium * 2;
     985            0 :             x2 = x;
     986            0 :             painter->drawLine(LineF(x, y, x2, y2));
     987              : 
     988            0 :             painter->setBrush(item->curColor(opt));
     989            0 :             painter->drawPolygon(arrowUp.translated(x2, y2));
     990              : 
     991            0 :             int idx = (pitch + 12) / 25;
     992            0 :             const char* l = item->label[idx];
     993            0 :             painter->setFont(f);
     994            0 :             painter->drawText(RectF(x2, y2, .0, .0),
     995              :                               muse::draw::AlignHCenter | muse::draw::AlignBottom,
     996              :                               muse::draw::TextDontClip,
     997            0 :                               String::fromAscii(l));
     998              : 
     999            0 :             y = y2;
    1000              :         }
    1001            0 :         if (pitch == item->points()[pt + 1].pitch) {
    1002            0 :             if (pt == (n - 2)) {
    1003            0 :                 break;
    1004              :             }
    1005            0 :             x2 = x + spatium;
    1006            0 :             y2 = y;
    1007            0 :             painter->drawLine(LineF(x, y, x2, y2));
    1008            0 :         } else if (pitch < item->points()[pt + 1].pitch) {
    1009              :             // up
    1010            0 :             x2 = x + spatium * .5;
    1011            0 :             y2 = -data->notePos.y() - spatium * 2;
    1012            0 :             double dx = x2 - x;
    1013            0 :             double dy = y2 - y;
    1014              : 
    1015            0 :             PainterPath path;
    1016            0 :             path.moveTo(x, y);
    1017            0 :             path.cubicTo(x + dx / 2, y, x2, y + dy / 4, x2, y2);
    1018            0 :             painter->setBrush(BrushStyle::NoBrush);
    1019            0 :             painter->drawPath(path);
    1020              : 
    1021            0 :             painter->setBrush(item->curColor(opt));
    1022            0 :             painter->drawPolygon(arrowUp.translated(x2, y2));
    1023              : 
    1024            0 :             int idx = (item->points()[pt + 1].pitch + 12) / 25;
    1025            0 :             const char* l = item->label[idx];
    1026            0 :             double ty = y2;       // - _spatium;
    1027            0 :             painter->setFont(f);
    1028            0 :             painter->drawText(RectF(x2, ty, .0, .0),
    1029              :                               muse::draw::AlignHCenter | muse::draw::AlignBottom,
    1030              :                               muse::draw::TextDontClip,
    1031            0 :                               String::fromAscii(l));
    1032            0 :         } else {
    1033              :             // down
    1034            0 :             x2 = x + spatium * .5;
    1035            0 :             y2 = y + spatium * 3;
    1036            0 :             double dx = x2 - x;
    1037            0 :             double dy = y2 - y;
    1038              : 
    1039            0 :             PainterPath path;
    1040            0 :             path.moveTo(x, y);
    1041            0 :             path.cubicTo(x + dx / 2, y, x2, y + dy / 4, x2, y2);
    1042            0 :             painter->setBrush(BrushStyle::NoBrush);
    1043            0 :             painter->drawPath(path);
    1044              : 
    1045            0 :             painter->setBrush(item->curColor(opt));
    1046            0 :             painter->drawPolygon(arrowDown.translated(x2, y2));
    1047            0 :         }
    1048            0 :         x = x2;
    1049            0 :         y = y2;
    1050              :     }
    1051            0 : }
    1052              : 
    1053            0 : void TDraw::draw(const Box* item, Painter* painter, const PaintOptions& opt)
    1054              : {
    1055              :     TRACE_DRAW_ITEM;
    1056            0 :     if (opt.isPrinting) {
    1057            0 :         return;
    1058              :     }
    1059              : 
    1060            0 :     const Box::LayoutData* ldata = item->ldata();
    1061              : 
    1062            0 :     const bool showHighlightedFrame = item->selected() || item->dropTarget();
    1063            0 :     const bool showFrame = showHighlightedFrame || (item->score() ? item->score()->showFrames() : false);
    1064              : 
    1065            0 :     if (showFrame) {
    1066            0 :         double lineWidth = item->defaultSpatium() * .10;
    1067            0 :         Pen pen;
    1068            0 :         pen.setWidthF(lineWidth);
    1069            0 :         pen.setJoinStyle(PenJoinStyle::RoundJoin);
    1070            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    1071            0 :         pen.setColor(showHighlightedFrame
    1072            0 :                      ? item->configuration()->selectionColor()
    1073            0 :                      : item->configuration()->frameColor());
    1074            0 :         pen.setDashPattern({ 5, 5 });
    1075              : 
    1076            0 :         painter->setBrush(BrushStyle::NoBrush);
    1077            0 :         painter->setPen(pen);
    1078            0 :         lineWidth *= 0.5;
    1079            0 :         painter->drawRect(ldata->bbox().adjusted(lineWidth, lineWidth, -lineWidth, -lineWidth));
    1080            0 :     }
    1081              : }
    1082              : 
    1083            0 : void TDraw::draw(const HBox* item, Painter* painter, const PaintOptions& opt)
    1084              : {
    1085            0 :     draw(static_cast<const Box*>(item), painter, opt);
    1086            0 : }
    1087              : 
    1088            0 : void TDraw::draw(const VBox* item, Painter* painter, const PaintOptions& opt)
    1089              : {
    1090            0 :     draw(static_cast<const Box*>(item), painter, opt);
    1091            0 : }
    1092              : 
    1093            0 : void TDraw::draw(const FBox* item, Painter* painter, const PaintOptions& opt)
    1094              : {
    1095            0 :     draw(static_cast<const Box*>(item), painter, opt);
    1096            0 : }
    1097              : 
    1098            0 : void TDraw::draw(const TBox* item, Painter* painter, const PaintOptions& opt)
    1099              : {
    1100            0 :     draw(static_cast<const Box*>(item), painter, opt);
    1101            0 : }
    1102              : 
    1103            0 : void TDraw::draw(const Bracket* item, Painter* painter, const PaintOptions& opt)
    1104              : {
    1105              :     TRACE_DRAW_ITEM;
    1106            0 :     const Bracket::LayoutData* ldata = item->ldata();
    1107            0 :     IF_ASSERT_FAILED(ldata) {
    1108            0 :         return;
    1109              :     }
    1110              : 
    1111            0 :     switch (item->bracketType()) {
    1112            0 :     case BracketType::BRACE: {
    1113            0 :         if (ldata->braceSymbol == SymId::noSym) {
    1114            0 :             painter->setNoPen();
    1115            0 :             painter->setBrush(Brush(item->curColor(opt)));
    1116            0 :             painter->drawPath(ldata->path);
    1117              :         } else {
    1118            0 :             double h = ldata->bracketHeight;
    1119            0 :             double glyphHeight = item->symHeight(ldata->braceSymbol);
    1120            0 :             double mag = h / glyphHeight;
    1121            0 :             painter->setPen(item->curColor(opt));
    1122            0 :             painter->save();
    1123            0 :             painter->scale(item->magx(), mag);
    1124            0 :             item->drawSymbol(ldata->braceSymbol, painter, PointF(0.0, glyphHeight));
    1125            0 :             painter->restore();
    1126              :         }
    1127              :     }
    1128            0 :     break;
    1129            0 :     case BracketType::NORMAL: {
    1130            0 :         double h = ldata->bracketHeight;
    1131            0 :         double spatium = item->spatium();
    1132            0 :         double w = item->style().styleAbsolute(Sid::bracketWidth);
    1133            0 :         double bd = (item->style().styleSt(Sid::musicalSymbolFont) == "Leland") ? spatium * .5 : spatium * .25;
    1134            0 :         Pen pen(item->curColor(opt), w, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1135            0 :         painter->setPen(pen);
    1136            0 :         painter->drawLine(LineF(0.0, -bd - w * .5, 0.0, h + bd + w * .5));
    1137            0 :         double x = -w * .5;
    1138            0 :         double y1 = -bd;
    1139            0 :         double y2 = h + bd;
    1140            0 :         item->drawSymbol(SymId::bracketTop, painter, PointF(x, y1));
    1141            0 :         item->drawSymbol(SymId::bracketBottom, painter, PointF(x, y2));
    1142            0 :     }
    1143            0 :     break;
    1144            0 :     case BracketType::SQUARE:
    1145              :     {
    1146            0 :         double h = ldata->bracketHeight;
    1147            0 :         double lineW = item->style().styleAbsolute(Sid::staffLineWidth);
    1148            0 :         double bracketWidth = ldata->bracketWidth - lineW / 2;
    1149            0 :         Pen pen(item->curColor(opt), lineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1150            0 :         painter->setPen(pen);
    1151            0 :         painter->drawLine(LineF(0.0, 0.0, 0.0, h));
    1152            0 :         painter->drawLine(LineF(-lineW / 2, 0.0, lineW / 2 + bracketWidth, 0.0));
    1153            0 :         painter->drawLine(LineF(-lineW / 2, h, lineW / 2 + bracketWidth, h));
    1154            0 :     }
    1155            0 :     break;
    1156            0 :     case BracketType::LINE: {
    1157            0 :         double h = ldata->bracketHeight;
    1158            0 :         double w = 0.67 * item->style().styleAbsolute(Sid::bracketWidth);
    1159            0 :         Pen pen(item->curColor(opt), w, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1160            0 :         painter->setPen(pen);
    1161            0 :         double bd = item->style().styleAbsolute(Sid::staffLineWidth) * 0.5;
    1162            0 :         painter->drawLine(LineF(0.0, -bd, 0.0, h + bd));
    1163            0 :     }
    1164            0 :     break;
    1165            0 :     case BracketType::GROUP:
    1166              :     {
    1167            0 :         if (!item->bracketItem()->showBracket() && (!item->score()->isShowInvisible() || opt.isPrinting)) {
    1168            0 :             return;
    1169              :         }
    1170              : 
    1171            0 :         painter->save();
    1172            0 :         setMask(item, painter);
    1173              : 
    1174            0 :         double h = ldata->bracketHeight;
    1175            0 :         double lineW = item->style().styleAbsolute(Sid::groupBracketLineWidth);
    1176            0 :         double hookLen = item->style().styleAbsolute(Sid::groupBracketHookLen);
    1177            0 :         Color color = item->curColor(item->visible() && item->bracketItem()->showBracket(), opt);
    1178            0 :         Pen pen(color, lineW, PenStyle::SolidLine, PenCapStyle::FlatCap);
    1179            0 :         painter->setPen(pen);
    1180            0 :         painter->drawLine(LineF(0.5 * lineW, 0.0, 0.5 * lineW, h));
    1181            0 :         painter->drawLine(LineF(0.0, 0.0, hookLen, 0.0));
    1182            0 :         painter->drawLine(LineF(0.0, h, hookLen, h));
    1183              : 
    1184            0 :         painter->restore();
    1185            0 :     }
    1186            0 :     break;
    1187            0 :     case BracketType::NO_BRACKET:
    1188            0 :         break;
    1189              :     }
    1190              : }
    1191              : 
    1192            0 : void TDraw::draw(const Breath* item, Painter* painter, const PaintOptions& opt)
    1193              : {
    1194              :     TRACE_DRAW_ITEM;
    1195            0 :     painter->setPen(item->curColor(opt));
    1196            0 :     item->drawSymbol(item->symId(), painter);
    1197            0 : }
    1198              : 
    1199            0 : void TDraw::draw(const ChordLine* item, Painter* painter, const PaintOptions& opt)
    1200              : {
    1201              :     TRACE_DRAW_ITEM;
    1202            0 :     const ChordLine::LayoutData* ldata = item->ldata();
    1203            0 :     IF_ASSERT_FAILED(ldata) {
    1204            0 :         return;
    1205              :     }
    1206              : 
    1207            0 :     painter->setPen(Pen(item->curColor(opt), item->style().styleAbsolute(Sid::chordlineThickness) * item->mag(), PenStyle::SolidLine));
    1208            0 :     painter->setBrush(BrushStyle::NoBrush);
    1209            0 :     if (!item->isWavy()) {
    1210            0 :         painter->drawPath(ldata->path);
    1211              :     } else {
    1212            0 :         painter->save();
    1213            0 :         painter->rotate((item->chordLineType() == ChordLineType::FALL ? 1 : -1));
    1214            0 :         item->drawSymbol(item->waveSym(), painter);
    1215            0 :         painter->restore();
    1216              :     }
    1217              : }
    1218              : 
    1219           10 : void TDraw::draw(const Clef* item, Painter* painter, const PaintOptions& opt)
    1220              : {
    1221              :     TRACE_DRAW_ITEM;
    1222           10 :     const Clef::LayoutData* ldata = item->ldata();
    1223           10 :     IF_ASSERT_FAILED(ldata) {
    1224            0 :         return;
    1225              :     }
    1226              : 
    1227           10 :     if (ldata->symId == SymId::noSym || (item->staff() && !const_cast<const Staff*>(item->staff())->staffType(item->tick())->genClef())) {
    1228            0 :         return;
    1229              :     }
    1230              : 
    1231           10 :     painter->setPen(item->curColor(opt));
    1232           10 :     item->drawSymbol(ldata->symId, painter);
    1233              : }
    1234              : 
    1235            0 : void TDraw::draw(const Capo* item, Painter* painter, const PaintOptions& opt)
    1236              : {
    1237            0 :     drawTextBase(item, painter, opt);
    1238            0 : }
    1239              : 
    1240            0 : void TDraw::draw(const DeadSlapped* item, Painter* painter, const PaintOptions& opt)
    1241              : {
    1242              :     TRACE_DRAW_ITEM;
    1243            0 :     const DeadSlapped::LayoutData* ldata = item->ldata();
    1244            0 :     IF_ASSERT_FAILED(ldata) {
    1245            0 :         return;
    1246              :     }
    1247              : 
    1248            0 :     painter->setPen(PenStyle::NoPen);
    1249            0 :     painter->setBrush(item->curColor(opt));
    1250            0 :     painter->drawPath(ldata->path1);
    1251            0 :     painter->drawPath(ldata->path2);
    1252              : }
    1253              : 
    1254            0 : void TDraw::draw(const Dynamic* item, Painter* painter, const PaintOptions& opt)
    1255              : {
    1256            0 :     drawTextBase(item, painter, opt);
    1257            0 : }
    1258              : 
    1259            0 : void TDraw::draw(const Expression* item, Painter* painter, const PaintOptions& opt)
    1260              : {
    1261            0 :     drawTextBase(item, painter, opt);
    1262            0 : }
    1263              : 
    1264            0 : void TDraw::draw(const Fermata* item, Painter* painter, const PaintOptions& opt)
    1265              : {
    1266              :     TRACE_DRAW_ITEM;
    1267            0 :     painter->setPen(item->curColor(opt));
    1268            0 :     item->drawSymbol(item->symId(), painter);
    1269            0 : }
    1270              : 
    1271            0 : void TDraw::draw(const FiguredBass* item, Painter* painter, const PaintOptions& opt)
    1272              : {
    1273              :     TRACE_DRAW_ITEM;
    1274            0 :     const FiguredBass::LayoutData* ldata = item->ldata();
    1275              :     // if not printing, draw duration line(s)
    1276            0 :     if (!opt.isPrinting && item->score()->showUnprintable()) {
    1277            0 :         for (double len : ldata->lineLengths) {
    1278            0 :             if (len > 0) {
    1279            0 :                 painter->setPen(Pen(item->configuration()->invisibleColor(), 3));
    1280            0 :                 painter->drawLine(0.0, -2, len, -2); // -2: 2 rast. un. above digits
    1281              :             }
    1282              :         }
    1283              :     }
    1284              : 
    1285            0 :     if (item->items().size() < 1) { // if not parseable into f.b. items
    1286            0 :         drawTextBase(item, painter, opt); // draw as standard text
    1287              :     } else {
    1288            0 :         for (FiguredBassItem* fi : item->items()) { // if parseable into f.b. items
    1289            0 :             painter->translate(fi->pos()); // draw each item in its proper position
    1290            0 :             draw(fi, painter, opt);
    1291            0 :             painter->translate(-fi->pos());
    1292              :         }
    1293              :     }
    1294            0 : }
    1295              : 
    1296            0 : void TDraw::draw(const FiguredBassItem* item, Painter* painter, const PaintOptions& opt)
    1297              : {
    1298              :     TRACE_DRAW_ITEM;
    1299              : 
    1300            0 :     const FiguredBassItem::LayoutData* ldata = item->ldata();
    1301            0 :     int font = 0;
    1302            0 :     double _spatium = item->spatium();
    1303              :     // set font from general style
    1304            0 :     Font f(FiguredBass::FBFonts().at(font).family, Font::Type::Tablature);
    1305              : 
    1306              :     // (use the same font selection as used in layout() above)
    1307            0 :     double m = item->style().styleD(Sid::figuredBassFontSize) * item->spatium() / item->defaultSpatium();
    1308            0 :     f.setPointSizeF(m);
    1309              : 
    1310            0 :     painter->setFont(f);
    1311            0 :     painter->setBrush(BrushStyle::NoBrush);
    1312            0 :     Pen pen(item->figuredBass()->curColor(opt), FiguredBass::FB_CONTLINE_THICKNESS.toAbsolute(_spatium), PenStyle::SolidLine,
    1313            0 :             PenCapStyle::RoundCap);
    1314            0 :     painter->setPen(pen);
    1315            0 :     painter->drawText(ldata->bbox(),
    1316              :                       muse::draw::AlignLeft | muse::draw::AlignTop,
    1317              :                       muse::draw::TextDontClip,
    1318            0 :                       ldata->displayText);
    1319              : 
    1320              :     // continuation line
    1321            0 :     double lineEndX = 0.0;
    1322            0 :     if (item->contLine() != FiguredBassItem::ContLine::NONE) {
    1323            0 :         double lineStartX  = ldata->textWidth;                           // by default, line starts right after text
    1324            0 :         if (lineStartX > 0.0) {
    1325            0 :             lineStartX += FiguredBass::FB_CONTLINE_LEFT_PADDING.toAbsolute(_spatium);          // if some text, give some room after it
    1326              :         }
    1327            0 :         lineEndX = item->figuredBass()->ldata()->printedLineLength;            // by default, line ends with item duration
    1328            0 :         if (lineEndX - lineStartX < 1.0) {                         // if line length < 1 sp, ignore it
    1329            0 :             lineEndX = 0.0;
    1330              :         }
    1331              : 
    1332              :         // if extended cont.line and no closing parenthesis: look at next FB element
    1333            0 :         if (item->contLine() > FiguredBassItem::ContLine::SIMPLE && item->parenth5() == FiguredBassItem::Parenthesis::NONE) {
    1334              :             FiguredBass* nextFB;
    1335              :             // if there is a contiguous FB element
    1336            0 :             if ((nextFB = item->figuredBass()->nextFiguredBass()) != 0) {
    1337              :                 // retrieve the X position (in page coords) of a possible cont. line of nextFB
    1338              :                 // on the same line of 'this'
    1339            0 :                 PointF pgPos = item->pagePos();
    1340            0 :                 double nextContPageX = nextFB->additionalContLineX(pgPos.y());
    1341              :                 // if an additional cont. line has been found, extend up to its initial X coord
    1342            0 :                 if (nextContPageX > 0) {
    1343            0 :                     lineEndX = nextContPageX - pgPos.x() + FiguredBass::FB_CONTLINE_OVERLAP.toAbsolute(_spatium);
    1344              :                 }
    1345              :                 // with a little bit of overlap
    1346              :                 else {
    1347            0 :                     lineEndX = item->figuredBass()->ldata()->lineLength(0);                  // if none found, draw to the duration end
    1348              :                 }
    1349              :             }
    1350              :         }
    1351              :         // if some line, draw it
    1352            0 :         if (lineEndX > 0.0) {
    1353            0 :             double h = ldata->bbox().height() * FiguredBass::FB_CONTLINE_HEIGHT;
    1354            0 :             painter->drawLine(lineStartX, h, lineEndX - ldata->pos().x(), h);
    1355              :         }
    1356              :     }
    1357              : 
    1358              :     // closing cont.line parenthesis
    1359            0 :     if (item->parenth5() != FiguredBassItem::Parenthesis::NONE) {
    1360            0 :         int x = lineEndX > 0.0 ? lineEndX : ldata->textWidth;
    1361            0 :         painter->drawText(RectF(x, 0, ldata->bbox().width(), ldata->bbox().height()),
    1362              :                           muse::draw::AlignLeft | muse::draw::AlignTop,
    1363              :                           muse::draw::TextDontClip,
    1364            0 :                           Char(FiguredBass::FBFonts().at(font).displayParenthesis[int(item->parenth5())].unicode()));
    1365              :     }
    1366            0 : }
    1367              : 
    1368            0 : void TDraw::draw(const Fingering* item, Painter* painter, const PaintOptions& opt)
    1369              : {
    1370              :     TRACE_DRAW_ITEM;
    1371            0 :     drawTextBase(item, painter, opt);
    1372            0 : }
    1373              : 
    1374            0 : void TDraw::draw(const FretDiagram* item, Painter* painter, const PaintOptions& opt)
    1375              : {
    1376              :     TRACE_DRAW_ITEM;
    1377            0 :     const FretDiagram::LayoutData* ldata = item->ldata();
    1378            0 :     PointF translation = -PointF(ldata->stringDist * (item->strings() - 1), 0);
    1379            0 :     if (item->orientation() == Orientation::HORIZONTAL) {
    1380            0 :         painter->save();
    1381            0 :         painter->rotate(-90);
    1382            0 :         painter->translate(translation);
    1383              :     }
    1384              : 
    1385              :     // Init pen and other values
    1386            0 :     Pen pen(item->curColor(opt));
    1387            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1388            0 :     painter->setBrush(Brush(Color(painter->pen().color())));
    1389              : 
    1390              :     // x2 is the x val of the rightmost string
    1391            0 :     double x2 = (item->strings() - 1) * ldata->stringDist;
    1392              : 
    1393              :     // Draw the nut
    1394            0 :     pen.setWidthF(ldata->nutLineWidth);
    1395            0 :     painter->setPen(pen);
    1396            0 :     double nutY = ldata->nutY;
    1397            0 :     painter->drawLine(LineF(-ldata->stringLineWidth * .5, nutY, x2 + ldata->stringLineWidth * .5, nutY));
    1398              : 
    1399              :     // Draw strings and frets
    1400            0 :     pen.setWidthF(ldata->stringLineWidth);
    1401            0 :     painter->setPen(pen);
    1402              : 
    1403              :     // y2 is the y val of the bottom fretline
    1404            0 :     double y1 = ldata->stringExtendTop;
    1405            0 :     double y2 = ldata->fretDist * item->frets() + 0.5 * ldata->stringLineWidth + ldata->stringExtendBottom;
    1406            0 :     for (int i = 0; i < item->strings(); ++i) {
    1407            0 :         double x = ldata->stringDist * i;
    1408            0 :         painter->drawLine(LineF(x, y1, x, y2));
    1409              :     }
    1410            0 :     for (int i = 1; i <= item->frets(); ++i) {
    1411            0 :         double y = ldata->fretDist * i;
    1412            0 :         painter->drawLine(LineF(0.0, y, x2, y));
    1413              :     }
    1414              : 
    1415              :     // dotd is the diameter of a dot
    1416            0 :     double dotd = ldata->dotDiameter;
    1417              : 
    1418              :     // Draw dots, sym pen is used to draw them (and markers)
    1419            0 :     Pen symPen(pen);
    1420            0 :     symPen.setCapStyle(PenCapStyle::FlatCap);
    1421              :     // Raise the miter limit so the triangle's apex isn't bevelled (needs ~2.24)
    1422            0 :     symPen.setJoinStyle(PenJoinStyle::MiterJoin);
    1423            0 :     symPen.setMiterLimit(3.0);
    1424            0 :     double symPenWidth = ldata->stringLineWidth * 1.2;
    1425            0 :     symPen.setWidthF(symPenWidth);
    1426              : 
    1427            0 :     for (auto const& i : item->dots()) {
    1428            0 :         for (auto const& d : i.second) {
    1429            0 :             if (!d.exists()) {
    1430            0 :                 continue;
    1431              :             }
    1432              : 
    1433            0 :             int string = i.first;
    1434            0 :             int fret = d.fret - 1;
    1435              : 
    1436              :             // Calculate coords of the top left corner of the dot
    1437            0 :             double x = ldata->stringDist * string - dotd * .5;
    1438            0 :             double y = ldata->fretDist * fret + ldata->fretDist * .5 - dotd * .5;
    1439              : 
    1440              :             // Draw different symbols
    1441            0 :             painter->setPen(symPen);
    1442            0 :             switch (d.dtype) {
    1443            0 :             case FretDotType::CROSS:
    1444              :                 // Give the cross a slightly larger width
    1445            0 :                 symPen.setWidthF(symPenWidth * 1.5);
    1446            0 :                 painter->setPen(symPen);
    1447            0 :                 painter->drawLine(LineF(x, y, x + dotd, y + dotd));
    1448            0 :                 painter->drawLine(LineF(x + dotd, y, x, y + dotd));
    1449            0 :                 symPen.setWidthF(symPenWidth);
    1450            0 :                 break;
    1451            0 :             case FretDotType::SQUARE:
    1452            0 :                 painter->setBrush(BrushStyle::NoBrush);
    1453            0 :                 painter->drawRect(RectF(x, y, dotd, dotd));
    1454            0 :                 break;
    1455            0 :             case FretDotType::TRIANGLE:
    1456            0 :                 painter->setBrush(BrushStyle::NoBrush);
    1457            0 :                 painter->drawPolygon(PolygonF({ PointF(x, y + dotd), PointF(x + .5 * dotd, y), PointF(x + dotd, y + dotd) }));
    1458            0 :                 break;
    1459            0 :             case FretDotType::NORMAL:
    1460              :             default:
    1461            0 :                 painter->setBrush(symPen.color());
    1462            0 :                 painter->setNoPen();
    1463            0 :                 painter->drawEllipse(RectF(x, y, dotd, dotd));
    1464            0 :                 break;
    1465              :             }
    1466              :         }
    1467              :     }
    1468              : 
    1469              :     // Draw markers
    1470            0 :     symPen.setWidthF(ldata->stringLineWidth * 1.2);
    1471            0 :     painter->setBrush(BrushStyle::NoBrush);
    1472            0 :     painter->setPen(symPen);
    1473            0 :     for (auto const& i : item->markers()) {
    1474            0 :         int string = i.first;
    1475            0 :         FretItem::Marker marker = i.second;
    1476            0 :         if (!marker.exists()) {
    1477            0 :             continue;
    1478              :         }
    1479              : 
    1480            0 :         double x = ldata->stringDist * string - ldata->markerSize * .5;
    1481            0 :         double y = ldata->markerY;
    1482            0 :         if (marker.mtype == FretMarkerType::CIRCLE) {
    1483            0 :             painter->drawEllipse(RectF(x, y, ldata->markerSize, ldata->markerSize));
    1484            0 :         } else if (marker.mtype == FretMarkerType::CROSS) {
    1485            0 :             painter->drawLine(PointF(x, y), PointF(x + ldata->markerSize, y + ldata->markerSize));
    1486            0 :             painter->drawLine(PointF(x, y + ldata->markerSize), PointF(x + ldata->markerSize, y));
    1487              :         }
    1488              :     }
    1489              : 
    1490              :     // Draw barres
    1491            0 :     for (auto const& i : item->barres()) {
    1492            0 :         int fret        = i.first;
    1493            0 :         int startString = i.second.startString;
    1494            0 :         int endString   = i.second.endString;
    1495              : 
    1496            0 :         double x1    = ldata->stringDist * startString;
    1497            0 :         double newX2 = endString == -1 ? x2 : ldata->stringDist * endString;
    1498            0 :         double y     = ldata->fretDist * (fret - 1) + ldata->fretDist * .5;
    1499            0 :         if (item->style().styleB(Sid::barreAppearanceSlur)) {
    1500            0 :             pen.setWidthF(0.25 * ldata->stringLineWidth);
    1501            0 :             pen.setCapStyle(PenCapStyle::RoundCap);
    1502            0 :             pen.setJoinStyle(PenJoinStyle::RoundJoin);
    1503            0 :             painter->setPen(pen);
    1504            0 :             painter->setBrush(Brush(pen.color()));
    1505            0 :             for (const PainterPath& path : ldata->slurPaths) {
    1506            0 :                 painter->drawPath(path);
    1507              :             }
    1508              :         } else {
    1509            0 :             pen.setWidthF(dotd * item->style().styleD(Sid::barreLineWidth));
    1510            0 :             pen.setCapStyle(PenCapStyle::RoundCap);
    1511            0 :             painter->setPen(pen);
    1512            0 :             painter->drawLine(LineF(x1, y, newX2, y));
    1513              :         }
    1514              :     }
    1515              : 
    1516              :     // Draw fret offset number
    1517            0 :     if (item->fretOffset() > 0) {
    1518            0 :         Font scaledFont(item->fretNumFont());
    1519            0 :         scaledFont.setPointSizeF(scaledFont.pointSizeF() * (item->spatium() / item->defaultSpatium()));
    1520            0 :         painter->setFont(scaledFont);
    1521            0 :         String text = ldata->fretText;
    1522              : 
    1523            0 :         if (item->orientation() == Orientation::VERTICAL) {
    1524            0 :             if (item->numPos() == 0) {
    1525            0 :                 painter->drawText(RectF(-ldata->fretNumPadding, .0, .0, ldata->fretDist),
    1526              :                                   muse::draw::AlignVCenter | muse::draw::AlignRight,
    1527              :                                   muse::draw::TextDontClip,
    1528              :                                   text);
    1529              :             } else {
    1530            0 :                 painter->drawText(RectF(x2 + ldata->fretNumPadding, .0, .0, ldata->fretDist),
    1531              :                                   muse::draw::AlignVCenter | muse::draw::AlignLeft,
    1532              :                                   muse::draw::TextDontClip,
    1533              :                                   text);
    1534              :             }
    1535            0 :         } else if (item->orientation() == Orientation::HORIZONTAL) {
    1536            0 :             painter->save();
    1537            0 :             painter->translate(-translation);
    1538            0 :             painter->rotate(90);
    1539            0 :             if (item->numPos() == 0) {
    1540            0 :                 painter->drawText(RectF(.0, ldata->stringDist * (item->strings() - 1), .0, .0),
    1541              :                                   muse::draw::AlignLeft,
    1542              :                                   muse::draw::TextDontClip,
    1543              :                                   text);
    1544              :             } else {
    1545            0 :                 painter->drawText(RectF(.0, .0, .0, .0),
    1546              :                                   muse::draw::AlignBottom | muse::draw::AlignLeft,
    1547              :                                   muse::draw::TextDontClip,
    1548              :                                   text);
    1549              :             }
    1550            0 :             painter->restore();
    1551              :         }
    1552            0 :         painter->setFont(item->fretNumFont());
    1553            0 :     }
    1554              : 
    1555            0 :     for (const FretDiagram::FingeringItem& fingeringItem : item->ldata()->fingeringItems) {
    1556            0 :         painter->save();
    1557              : 
    1558            0 :         Font scaledFont(item->fingeringFont());
    1559            0 :         scaledFont.setPointSizeF(scaledFont.pointSizeF() * (item->spatium() / item->defaultSpatium()));
    1560            0 :         painter->setFont(scaledFont);
    1561            0 :         if (item->orientation() == Orientation::HORIZONTAL) {
    1562            0 :             painter->translate(-translation);
    1563            0 :             painter->rotate(90);
    1564              :         }
    1565              : 
    1566            0 :         painter->drawText(fingeringItem.pos, fingeringItem.fingerNumber);
    1567              : 
    1568            0 :         painter->restore();
    1569            0 :     }
    1570              : 
    1571            0 :     if (item->orientation() == Orientation::HORIZONTAL) {
    1572            0 :         painter->restore();
    1573              :     }
    1574            0 : }
    1575              : 
    1576            0 : static void setDashAndGapLen(const SLine* line, double& dash, double& gap, Pen& pen)
    1577              : {
    1578              :     static constexpr double DOTTED_DASH_LEN = 0.01;
    1579              :     static constexpr double DOTTED_GAP_LEN = 1.99;
    1580            0 :     switch (line->lineStyle()) {
    1581            0 :     case LineType::SOLID:
    1582            0 :         break;
    1583            0 :     case LineType::DASHED:
    1584            0 :         dash = line->dashLineLen(), gap = line->dashGapLen();
    1585            0 :         break;
    1586            0 :     case LineType::DOTTED:
    1587            0 :         dash = DOTTED_DASH_LEN, gap = DOTTED_GAP_LEN;
    1588            0 :         pen.setCapStyle(PenCapStyle::RoundCap); // round dots
    1589            0 :         break;
    1590              :     }
    1591            0 : }
    1592              : 
    1593            0 : static std::vector<double> distributedDashPattern(double dash, double gap, double lineLength)
    1594              : {
    1595            0 :     int numPairs = std::max(1.0, lineLength / (dash + gap));
    1596            0 :     double newGap = (lineLength - dash * (numPairs + 1)) / numPairs;
    1597              : 
    1598            0 :     return { dash, newGap };
    1599              : }
    1600              : 
    1601            0 : void TDraw::draw(const GlissandoSegment* item, Painter* painter, const PaintOptions& opt)
    1602              : {
    1603              :     TRACE_DRAW_ITEM;
    1604              : 
    1605            0 :     if (item->pos2().x() <= 0) {
    1606            0 :         return;
    1607              :     }
    1608              : 
    1609            0 :     painter->save();
    1610            0 :     double _spatium = item->spatium();
    1611            0 :     const Glissando* glissando = item->glissando();
    1612              : 
    1613            0 :     Pen pen(item->curColor(item->getProperty(Pid::VISIBLE).toBool(), item->getProperty(Pid::COLOR).value<Color>(), opt));
    1614            0 :     pen.setWidthF(item->absoluteFromSpatium(item->lineWidth()));
    1615            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1616            0 :     painter->setPen(pen);
    1617              : 
    1618              :     // rotate painter so that the line become horizontal
    1619            0 :     double w     = item->pos2().x();
    1620            0 :     double h     = item->pos2().y();
    1621            0 :     double l     = sqrt(w * w + h * h);
    1622            0 :     double wi    = asin(-h / l) * 180.0 / M_PI;
    1623            0 :     painter->rotate(-wi);
    1624              : 
    1625            0 :     if (glissando->glissandoType() == GlissandoType::STRAIGHT) {
    1626            0 :         const bool isNonSolid = glissando->lineStyle() != LineType::SOLID;
    1627            0 :         if (isNonSolid) {
    1628            0 :             double lineWidth = glissando->absoluteFromSpatium(glissando->lineWidth());
    1629            0 :             double dash = 0;
    1630            0 :             double gap = 0;
    1631            0 :             setDashAndGapLen(glissando, dash, gap, pen);
    1632            0 :             pen.setDashPattern(distributedDashPattern(dash, gap, l / lineWidth));
    1633            0 :             painter->setPen(pen);
    1634              :         }
    1635              : 
    1636            0 :         painter->drawLine(LineF(0.0, 0.0, l, 0.0));
    1637            0 :     } else if (glissando->glissandoType() == GlissandoType::WAVY) {
    1638            0 :         RectF b = item->symBbox(SymId::wiggleGlissando);
    1639            0 :         double a  = item->symAdvance(SymId::wiggleGlissando);
    1640            0 :         int n    = static_cast<int>(l / a);          // always round down (truncate) to avoid overlap
    1641            0 :         double x  = (l - n * a) * 0.5;     // centre line in available space
    1642            0 :         SymIdList ids;
    1643            0 :         for (int i = 0; i < n; ++i) {
    1644            0 :             ids.push_back(SymId::wiggleGlissando);
    1645              :         }
    1646              : 
    1647            0 :         item->score()->engravingFont()->draw(ids, painter, item->magS(), PointF(x, -(b.y() + b.height() * 0.5)));
    1648            0 :     }
    1649              : 
    1650            0 :     if (glissando->showText()) {
    1651            0 :         Font f(glissando->fontFace(), Font::Type::Unknown);
    1652            0 :         f.setPointSizeF(glissando->fontSize() * _spatium / item->defaultSpatium());
    1653            0 :         f.setBold(glissando->fontStyle() & FontStyle::Bold);
    1654            0 :         f.setItalic(glissando->fontStyle() & FontStyle::Italic);
    1655            0 :         f.setUnderline(glissando->fontStyle() & FontStyle::Underline);
    1656            0 :         f.setStrike(glissando->fontStyle() & FontStyle::Strike);
    1657            0 :         FontMetrics fm(f);
    1658            0 :         RectF r = fm.boundingRect(glissando->text());
    1659              : 
    1660              :         // if text longer than available space, skip it
    1661            0 :         if (r.width() < l) {
    1662            0 :             double x = (l - r.width()) * 0.5;
    1663            0 :             double yOffset = r.height() + r.y(); // find text descender height
    1664              :             // raise text slightly above line and slightly more with WAVY than with STRAIGHT
    1665            0 :             yOffset += _spatium * (glissando->glissandoType() == GlissandoType::WAVY ? 0.4 : 0.1);
    1666              : 
    1667            0 :             painter->setFont(f);
    1668            0 :             painter->drawText(PointF(x, -yOffset), glissando->text());
    1669              :         }
    1670            0 :     }
    1671            0 :     painter->restore();
    1672            0 : }
    1673              : 
    1674            0 : void TDraw::draw(const GuitarBendSegment* item, Painter* painter, const PaintOptions& opt)
    1675              : {
    1676              :     TRACE_DRAW_ITEM;
    1677              : 
    1678            0 :     bool tabStaff = item->staff()->isTabStaff(item->tick());
    1679            0 :     GuitarBend* bend = item->guitarBend();
    1680              : 
    1681            0 :     Pen pen(item->curColor(opt));
    1682            0 :     if (bend->bendType() == GuitarBendType::SCOOP) {
    1683            0 :         painter->setPen(pen);
    1684            0 :         item->drawSymbol(SymId::guitarVibratoBarScoop, painter);
    1685            0 :         return;
    1686              :     }
    1687              : 
    1688            0 :     pen.setWidthF(item->lineWidth());
    1689            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1690            0 :     pen.setJoinStyle(bend->bendType() == GuitarBendType::DIP ? PenJoinStyle::BevelJoin : PenJoinStyle::MiterJoin);
    1691            0 :     pen.setColor(item->curColor(opt));
    1692            0 :     if (tabStaff && bend->bendType() == GuitarBendType::PRE_DIVE) {
    1693            0 :         const PainterPath& path = item->ldata()->path();
    1694            0 :         if (path.elementCount() > 1) {
    1695            0 :             double lineLength = std::abs(item->ldata()->path().elementAt(1).y);
    1696            0 :             pen.setDashPattern(distributedDashPattern(3, 3, lineLength / pen.widthF()));
    1697              :         } else {
    1698            0 :             pen.setDashPattern({ 3, 3 });
    1699              :         }
    1700              :     }
    1701            0 :     painter->setPen(pen);
    1702              : 
    1703            0 :     Brush brush;
    1704            0 :     brush.setStyle(BrushStyle::NoBrush);
    1705            0 :     painter->setBrush(brush);
    1706              : 
    1707            0 :     painter->drawPath(item->ldata()->path());
    1708              : 
    1709            0 :     if (tabStaff) {
    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(item->ldata()->arrow());
    1715              :     }
    1716            0 : }
    1717              : 
    1718            0 : void TDraw::draw(const GuitarBendHoldSegment* item, Painter* painter, const PaintOptions& opt)
    1719              : {
    1720              :     TRACE_DRAW_ITEM;
    1721              : 
    1722            0 :     Pen pen(item->curColor(item->visible(), opt));
    1723            0 :     if (!item->ldata()->symIds().empty()) {
    1724            0 :         painter->setPen(pen);
    1725            0 :         item->drawSymbols(item->ldata()->symIds(), painter);
    1726            0 :         return;
    1727              :     }
    1728              : 
    1729            0 :     pen.setWidthF(item->lineWidth());
    1730            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    1731              : 
    1732            0 :     switch (item->getProperty(Pid::LINE_STYLE).value<LineType>()) {
    1733            0 :     case LineType::DASHED:
    1734              :     {
    1735            0 :         double dash = item->dashLength();
    1736            0 :         pen.setDashPattern(distributedDashPattern(dash, dash, item->pos2().x() / pen.widthF()));
    1737            0 :         break;
    1738              :     }
    1739            0 :     case LineType::DOTTED:
    1740            0 :         pen.setCapStyle(PenCapStyle::RoundCap);           // True dots
    1741            0 :         pen.setDashPattern({ 0.01, 1.99 });
    1742            0 :         break;
    1743            0 :     default:
    1744            0 :         break;
    1745              :     }
    1746              : 
    1747            0 :     pen.setJoinStyle(PenJoinStyle::MiterJoin);
    1748            0 :     painter->setPen(pen);
    1749              : 
    1750            0 :     painter->drawLine(PointF(), item->pos2());
    1751            0 : }
    1752              : 
    1753            0 : void TDraw::drawTextBase(const TextBase* item, Painter* painter, const PaintOptions& opt)
    1754              : {
    1755              :     TRACE_DRAW_ITEM;
    1756              : 
    1757            0 :     painter->save();
    1758            0 :     painter->rotate(item->textAngle());
    1759              : 
    1760            0 :     const TextBase::LayoutData* ldata = item->ldata();
    1761            0 :     if (item->hasFrame()) {
    1762            0 :         double baseSpatium = DefaultStyle::baseStyle().value(Sid::spatium).toReal();
    1763            0 :         if (!RealIsNull(item->frameWidth().val())) {
    1764            0 :             Color fColor = item->curColor(item->visible(), item->frameColor(), opt);
    1765            0 :             double frameWidthVal = item->frameWidth().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    1766              : 
    1767            0 :             Pen pen(fColor, frameWidthVal, PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin);
    1768            0 :             painter->setPen(pen);
    1769            0 :         } else {
    1770            0 :             painter->setNoPen();
    1771              :         }
    1772            0 :         Color bg(item->bgColor());
    1773            0 :         painter->setBrush(bg.alpha() ? Brush(bg) : BrushStyle::NoBrush);
    1774            0 :         if (item->circle()) {
    1775            0 :             painter->drawEllipse(ldata->frame);
    1776              :         } else {
    1777            0 :             double frameRadius = item->frameRound().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    1778            0 :             painter->drawRoundedRect(ldata->frame, frameRadius, frameRadius);
    1779              :         }
    1780              :     }
    1781            0 :     painter->setBrush(BrushStyle::NoBrush);
    1782            0 :     painter->setPen(item->textColor(opt));
    1783            0 :     for (const TextBlock& t : ldata->blocks) {
    1784            0 :         draw(t, item, painter);
    1785              :     }
    1786              : 
    1787            0 :     painter->restore();
    1788            0 : }
    1789              : 
    1790            0 : void TDraw::draw(const TextBlock& textBlock, const TextBase* item, Painter* painter)
    1791              : {
    1792            0 :     painter->translate(0.0, textBlock.y());
    1793            0 :     for (const TextFragment& f : textBlock.fragments()) {
    1794            0 :         draw(f, item, painter);
    1795              :     }
    1796            0 :     painter->translate(0.0, -textBlock.y());
    1797            0 : }
    1798              : 
    1799            0 : void TDraw::draw(const TextFragment& textFragment, const TextBase* item, muse::draw::Painter* painter)
    1800              : {
    1801            0 :     painter->setFont(textFragment.font(item));
    1802            0 :     painter->drawText(textFragment.pos, textFragment.text);
    1803            0 : }
    1804              : 
    1805            0 : void TDraw::drawTextLineBaseSegment(const TextLineBaseSegment* item, Painter* painter, const PaintOptions& opt)
    1806              : {
    1807            0 :     const TextLineBase* tl = item->textLineBase();
    1808            0 :     const TextLineBaseSegment::LayoutData* ldata = item->ldata();
    1809              : 
    1810            0 :     if (!item->text()->empty()) {
    1811            0 :         painter->translate(item->text()->pos());
    1812            0 :         item->text()->setVisible(tl->visible());
    1813            0 :         draw(item->text(), painter, opt);
    1814            0 :         painter->translate(-item->text()->pos());
    1815              :     }
    1816              : 
    1817            0 :     if (!item->endText()->empty()) {
    1818            0 :         painter->translate(item->endText()->pos());
    1819            0 :         item->endText()->setVisible(tl->visible());
    1820            0 :         draw(item->endText(), painter, opt);
    1821            0 :         painter->translate(-item->endText()->pos());
    1822              :     }
    1823              : 
    1824            0 :     if (ldata->npoints == 0
    1825            0 :         || ((opt.isPrinting || (item->score() && !item->score()->isShowInvisible()))
    1826            0 :             && !tl->lineVisible())) {
    1827            0 :         return;
    1828              :     }
    1829              : 
    1830              :     // color for line (text color comes from the text properties)
    1831            0 :     Color color = item->curColor(tl->visible() && tl->lineVisible(), tl->lineColor(), opt);
    1832              : 
    1833            0 :     double lineWidth = tl->absoluteFromSpatium(tl->lineWidth());
    1834              : 
    1835            0 :     const Pen solidPen(color, lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap, PenJoinStyle::MiterJoin);
    1836            0 :     Pen pen(solidPen);
    1837              : 
    1838            0 :     double dash = 0;
    1839            0 :     double gap = 0;
    1840              : 
    1841            0 :     setDashAndGapLen(tl, dash, gap, pen);
    1842              : 
    1843            0 :     const bool isNonSolid = tl->lineStyle() != LineType::SOLID;
    1844              : 
    1845              :     // Draw lines
    1846            0 :     if (item->twoLines()) { // hairpins
    1847            0 :         if (isNonSolid) {
    1848            0 :             pen.setDashPattern({ dash, gap });
    1849              :         }
    1850              : 
    1851            0 :         pen.setJoinStyle(PenJoinStyle::BevelJoin);
    1852            0 :         painter->setPen(pen);
    1853            0 :         if (!ldata->joinedHairpin.empty() && !isNonSolid) {
    1854            0 :             painter->drawPolyline(ldata->joinedHairpin);
    1855              :         } else {
    1856            0 :             painter->drawLines(&ldata->points[0], 2);
    1857              :         }
    1858            0 :         return;
    1859              :     }
    1860              : 
    1861            0 :     int start = 0, end = ldata->npoints;
    1862              : 
    1863              :     // Draw begin hook, if it needs to be drawn separately
    1864            0 :     if (item->isSingleBeginType() && tl->beginHookType() != HookType::NONE) {
    1865            0 :         if (tl->beginHookType() == HookType::ARROW_FILLED) {
    1866            0 :             Brush brush;
    1867            0 :             brush.setStyle(BrushStyle::SolidPattern);
    1868            0 :             brush.setColor(color);
    1869            0 :             painter->setBrush(brush);
    1870            0 :             painter->setNoPen();
    1871            0 :             painter->drawPolygon(ldata->beginArrow);
    1872            0 :         } else if (tl->beginHookType() == HookType::ARROW) {
    1873            0 :             pen.setJoinStyle(PenJoinStyle::MiterJoin);
    1874            0 :             painter->setPen(pen);
    1875            0 :             painter->drawPolyline(ldata->beginArrow);
    1876              :         } else {
    1877            0 :             bool isTHook = tl->beginHookType() == HookType::HOOK_90T;
    1878              : 
    1879            0 :             if (isNonSolid || isTHook) {
    1880            0 :                 const PointF& p1 = ldata->points[start++];
    1881            0 :                 const PointF& p2 = ldata->points[start++];
    1882              : 
    1883            0 :                 if (isTHook) {
    1884            0 :                     painter->setPen(solidPen);
    1885              :                 } else {
    1886            0 :                     double hookLength = sqrt(PointF::dotProduct(p2 - p1, p2 - p1));
    1887            0 :                     pen.setDashPattern(distributedDashPattern(dash, gap, hookLength / lineWidth));
    1888            0 :                     painter->setPen(pen);
    1889              :                 }
    1890              : 
    1891            0 :                 painter->drawLine(p1, p2);
    1892              :             }
    1893              :         }
    1894              :     }
    1895              : 
    1896              :     // Draw end hook, if it needs to be drawn separately
    1897            0 :     if (item->isSingleEndType() && tl->endHookType() != HookType::NONE) {
    1898            0 :         if (tl->endHookType() == HookType::ARROW_FILLED) {
    1899            0 :             Brush brush;
    1900            0 :             brush.setStyle(BrushStyle::SolidPattern);
    1901            0 :             brush.setColor(color);
    1902            0 :             painter->setBrush(brush);
    1903            0 :             painter->setNoPen();
    1904            0 :             painter->drawPolygon(ldata->endArrow);
    1905            0 :         } else if (tl->endHookType() == HookType::ARROW) {
    1906            0 :             pen.setJoinStyle(PenJoinStyle::MiterJoin);
    1907            0 :             painter->setPen(pen);
    1908            0 :             painter->drawPolyline(ldata->endArrow);
    1909              :         } else {
    1910            0 :             bool isTHook = tl->endHookType() == HookType::HOOK_90T;
    1911              : 
    1912            0 :             if (isNonSolid || isTHook) {
    1913            0 :                 const PointF& p1 = ldata->points[--end];
    1914            0 :                 const PointF& p2 = ldata->points[--end];
    1915              : 
    1916            0 :                 if (isTHook) {
    1917            0 :                     painter->setPen(solidPen);
    1918              :                 } else {
    1919            0 :                     double hookLength = sqrt(PointF::dotProduct(p2 - p1, p2 - p1));
    1920            0 :                     pen.setDashPattern(distributedDashPattern(dash, gap, hookLength / lineWidth));
    1921            0 :                     painter->setPen(pen);
    1922              :                 }
    1923              : 
    1924            0 :                 painter->drawLine(p1, p2);
    1925              :             }
    1926              :         }
    1927              :     }
    1928              : 
    1929              :     // Draw the rest
    1930            0 :     if (isNonSolid) {
    1931            0 :         pen.setDashPattern(distributedDashPattern(dash, gap, ldata->lineLength / lineWidth));
    1932              :     }
    1933              : 
    1934            0 :     painter->setPen(pen);
    1935            0 :     painter->drawPolyline(&ldata->points[start], end - start);
    1936            0 : }
    1937              : 
    1938            0 : void TDraw::draw(const GradualTempoChangeSegment* item, Painter* painter, const PaintOptions& opt)
    1939              : {
    1940              :     TRACE_DRAW_ITEM;
    1941            0 :     drawTextLineBaseSegment(item, painter, opt);
    1942            0 : }
    1943              : 
    1944            0 : void TDraw::draw(const HairpinSegment* item, Painter* painter, const PaintOptions& opt)
    1945              : {
    1946              :     TRACE_DRAW_ITEM;
    1947              : 
    1948            0 :     drawTextLineBaseSegment(item, painter, opt);
    1949              : 
    1950            0 :     if (item->drawCircledTip()) {
    1951            0 :         Color color = item->curColor(item->hairpin()->visible(), item->hairpin()->lineColor(), opt);
    1952            0 :         double w = item->absoluteFromSpatium(item->lineWidth());
    1953            0 :         if (item->staff()) {
    1954            0 :             w *= item->staff()->staffMag(item->hairpin()->tick());
    1955              :         }
    1956              : 
    1957            0 :         Pen pen(color, w);
    1958            0 :         painter->setPen(pen);
    1959            0 :         painter->setBrush(BrushStyle::NoBrush);
    1960            0 :         painter->drawEllipse(item->circledTip(), item->circledTipRadius(), item->circledTipRadius());
    1961            0 :     }
    1962            0 : }
    1963              : 
    1964            0 : void TDraw::draw(const HammerOnPullOffSegment* item, muse::draw::Painter* painter, const PaintOptions& opt)
    1965              : {
    1966            0 :     draw(toSlurSegment(item), painter, opt);
    1967            0 : }
    1968              : 
    1969            0 : void TDraw::draw(const HammerOnPullOffText* item, muse::draw::Painter* painter, const PaintOptions& opt)
    1970              : {
    1971              :     TRACE_DRAW_ITEM;
    1972            0 :     drawTextBase(item, painter, opt);
    1973            0 : }
    1974              : 
    1975            0 : void TDraw::draw(const HarpPedalDiagram* item, Painter* painter, const PaintOptions& opt)
    1976              : {
    1977              :     TRACE_DRAW_ITEM;
    1978            0 :     drawTextBase(item, painter, opt);
    1979            0 : }
    1980              : 
    1981            0 : void TDraw::draw(const HarmonicMarkSegment* item, Painter* painter, const PaintOptions& opt)
    1982              : {
    1983              :     TRACE_DRAW_ITEM;
    1984            0 :     drawTextLineBaseSegment(item, painter, opt);
    1985            0 : }
    1986              : 
    1987            0 : void TDraw::draw(const Harmony* item, Painter* painter, const PaintOptions& opt)
    1988              : {
    1989              :     TRACE_DRAW_ITEM;
    1990              : 
    1991            0 :     const Harmony::LayoutData* ldata = item->ldata();
    1992              : 
    1993            0 :     if (ldata->renderItemList().empty()) {
    1994            0 :         drawTextBase(item, painter, opt);
    1995            0 :         return;
    1996              :     }
    1997              : 
    1998            0 :     if (item->hasFrame()) {
    1999            0 :         if (!RealIsNull(item->frameWidth().val())) {
    2000            0 :             Color color = item->frameColor();
    2001            0 :             Pen pen(color, item->frameWidth().val() * item->spatium(), PenStyle::SolidLine,
    2002            0 :                     PenCapStyle::SquareCap, PenJoinStyle::MiterJoin);
    2003            0 :             painter->setPen(pen);
    2004            0 :         } else {
    2005            0 :             painter->setNoPen();
    2006              :         }
    2007            0 :         Color bg(item->bgColor());
    2008            0 :         painter->setBrush(bg.alpha() ? Brush(bg) : BrushStyle::NoBrush);
    2009            0 :         if (item->circle()) {
    2010            0 :             painter->drawArc(ldata->frame, 0, 5760);
    2011              :         } else {
    2012            0 :             double baseSpatium = DefaultStyle::baseStyle().value(Sid::spatium).toReal();
    2013            0 :             double frameRadius = item->frameRound().val() * (item->sizeIsSpatiumDependent() ? item->spatium() : baseSpatium);
    2014            0 :             painter->drawRoundedRect(ldata->frame, frameRadius, frameRadius);
    2015              :         }
    2016              :     }
    2017            0 :     painter->setBrush(BrushStyle::NoBrush);
    2018            0 :     Color color = item->textColor(opt);
    2019            0 :     painter->setPen(color);
    2020            0 :     for (const HarmonyRenderItem* renderItem : ldata->renderItemList()) {
    2021            0 :         if (const TextSegment* ts = dynamic_cast<const TextSegment*>(renderItem)) {
    2022            0 :             painter->setFont(ts->font());
    2023            0 :             painter->drawText(ts->pos(), ts->text());
    2024            0 :         } else if (const ChordSymbolParen* parenItem = dynamic_cast<const ChordSymbolParen*>(renderItem)) {
    2025            0 :             Parenthesis* p = parenItem->parenItem;
    2026            0 :             painter->translate(parenItem->pos());
    2027            0 :             draw(p, painter, opt);
    2028            0 :             painter->translate(-parenItem->pos());
    2029              :         }
    2030              :     }
    2031              : 
    2032            0 :     if (item->isPolychord()) {
    2033            0 :         Pen pen(painter->pen());
    2034            0 :         pen.setWidthF(item->absoluteFromSpatium(item->style().styleS(Sid::polychordDividerThickness)));
    2035            0 :         pen.setColor(color);
    2036            0 :         painter->setPen(pen);
    2037            0 :         for (const LineF& line : ldata->polychordDividerLines()) {
    2038            0 :             painter->drawLine(line.translated(PointF(0.0, ldata->polychordDividerOffset)));
    2039              :         }
    2040            0 :     }
    2041              : }
    2042              : 
    2043            0 : void TDraw::draw(const Hook* item, Painter* painter, const PaintOptions& opt)
    2044              : {
    2045              :     TRACE_DRAW_ITEM;
    2046              :     // hide if belonging to the second chord of a cross-measure pair
    2047            0 :     if (item->chord() && item->chord()->crossMeasure() == CrossMeasure::SECOND) {
    2048            0 :         return;
    2049              :     }
    2050              : 
    2051            0 :     painter->setPen(item->curColor(opt));
    2052            0 :     item->drawSymbol(item->sym(), painter);
    2053              : }
    2054              : 
    2055            0 : void TDraw::draw(const Image* item, Painter* painter, const PaintOptions& opt)
    2056              : {
    2057              :     TRACE_DRAW_ITEM;
    2058            0 :     const Image::LayoutData* ldata = item->ldata();
    2059            0 :     bool emptyImage = false;
    2060            0 :     if (item->imageType() == ImageType::SVG) {
    2061            0 :         if (!item->svgRenderer()) {
    2062            0 :             emptyImage = true;
    2063              :         } else {
    2064            0 :             item->svgRenderer()->render(painter, ldata->bbox());
    2065              :         }
    2066            0 :     } else if (item->imageType() == ImageType::RASTER) {
    2067            0 :         if (item->rasterImage() == nullptr) {
    2068            0 :             emptyImage = true;
    2069              :         } else {
    2070            0 :             painter->save();
    2071            0 :             SizeF s;
    2072            0 :             if (item->sizeIsSpatium()) {
    2073            0 :                 s = item->size() * item->spatium();
    2074              :             } else {
    2075            0 :                 s = item->size() * DPMM;
    2076              :             }
    2077            0 :             painter->scale(s.width() / item->rasterImage()->width(), s.height() / item->rasterImage()->height());
    2078            0 :             painter->drawPixmap(PointF(0, 0), *item->rasterImage());
    2079            0 :             painter->restore();
    2080              :         }
    2081              :     }
    2082              : 
    2083            0 :     if (emptyImage) {
    2084            0 :         painter->setBrush(BrushStyle::NoBrush);
    2085            0 :         painter->setPen(item->configuration()->defaultColor());
    2086            0 :         painter->drawRect(ldata->bbox());
    2087            0 :         painter->drawLine(0.0, 0.0, ldata->bbox().width(), ldata->bbox().height());
    2088            0 :         painter->drawLine(ldata->bbox().width(), 0.0, 0.0, ldata->bbox().height());
    2089              :     }
    2090            0 :     if (item->selected() && !opt.isPrinting) {
    2091            0 :         painter->setBrush(BrushStyle::NoBrush);
    2092            0 :         painter->setPen(item->configuration()->selectionColor());
    2093            0 :         painter->drawRect(ldata->bbox());
    2094              :     }
    2095            0 : }
    2096              : 
    2097            0 : void TDraw::draw(const InstrumentChange* item, Painter* painter, const PaintOptions& opt)
    2098              : {
    2099              :     TRACE_DRAW_ITEM;
    2100            0 :     drawTextBase(item, painter, opt);
    2101            0 : }
    2102              : 
    2103            0 : void TDraw::draw(const InstrumentName* item, Painter* painter, const PaintOptions& opt)
    2104              : {
    2105              :     TRACE_DRAW_ITEM;
    2106            0 :     drawTextBase(item, painter, opt);
    2107            0 : }
    2108              : 
    2109            0 : void TDraw::draw(const Jump* item, Painter* painter, const PaintOptions& opt)
    2110              : {
    2111              :     TRACE_DRAW_ITEM;
    2112            0 :     drawTextBase(item, painter, opt);
    2113            0 : }
    2114              : 
    2115            0 : void TDraw::draw(const KeySig* item, Painter* painter, const PaintOptions& opt)
    2116              : {
    2117              :     TRACE_DRAW_ITEM;
    2118            0 :     const KeySig::LayoutData* ldata = item->ldata();
    2119              : 
    2120            0 :     painter->setPen(item->curColor(opt));
    2121            0 :     double _spatium = item->spatium();
    2122            0 :     double step = _spatium * (item->staff() ? item->staff()->staffTypeForElement(item)->lineDistance().val() * 0.5 : 0.5);
    2123            0 :     int lines = item->staff() ? item->staff()->staffTypeForElement(item)->lines() : 5;
    2124            0 :     double ledgerLineWidth = item->style().styleAbsolute(Sid::ledgerLineWidth) * item->mag();
    2125            0 :     double ledgerExtraLen = item->style().styleS(Sid::ledgerLineLength).val() * _spatium;
    2126            0 :     for (const KeySym& ks : ldata->keySymbols) {
    2127            0 :         double x = ks.xPos.toAbsolute(_spatium);
    2128            0 :         double y = ks.line * step;
    2129            0 :         item->drawSymbol(ks.sym, painter, PointF(x, y));
    2130              :         // ledger lines
    2131            0 :         double _symWidth = item->symWidth(ks.sym);
    2132            0 :         double x1 = x - ledgerExtraLen;
    2133            0 :         double x2 = x + _symWidth + ledgerExtraLen;
    2134            0 :         painter->setPen(Pen(item->curColor(opt), ledgerLineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    2135            0 :         for (int i = -2; i >= ks.line; i -= 2) { // above
    2136            0 :             y = i * step;
    2137            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2138              :         }
    2139            0 :         for (int i = lines * 2; i <= ks.line; i += 2) { // below
    2140            0 :             y = i * step;
    2141            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2142              :         }
    2143              :     }
    2144            0 : }
    2145              : 
    2146            0 : void TDraw::draw(const LaissezVibSegment* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2147              : {
    2148            0 :     const LaissezVibSegment::LayoutData* ldata = item->ldata();
    2149            0 :     if (item->score()->style().styleB(Sid::laissezVibUseSmuflSym)) {
    2150            0 :         painter->setPen(item->curColor(opt));
    2151            0 :         item->drawSymbol(ldata->symbol, painter);
    2152              :     } else {
    2153            0 :         draw(static_cast<const TieSegment*>(item), painter, opt);
    2154              :     }
    2155            0 : }
    2156              : 
    2157            0 : void TDraw::draw(const Lasso* item, Painter* painter, const PaintOptions&)
    2158              : {
    2159              :     TRACE_DRAW_ITEM;
    2160            0 :     const Lasso::LayoutData* ldata = item->ldata();
    2161            0 :     painter->setBrush(Brush(item->configuration()->lassoColor()));
    2162              :     // always 2 pixel width
    2163            0 :     double w = 2.0 / painter->worldTransform().m11() * item->contextConfiguration()->guiScaling();
    2164            0 :     painter->setPen(Pen(item->configuration()->selectionColor(), w));
    2165            0 :     painter->drawRect(ldata->bbox());
    2166            0 : }
    2167              : 
    2168            0 : void TDraw::draw(const LayoutBreak* item, Painter* painter, const PaintOptions& opt)
    2169              : {
    2170              :     TRACE_DRAW_ITEM;
    2171              : 
    2172            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    2173            0 :         return;
    2174              :     }
    2175              : 
    2176            0 :     Color selectionColor = opt.invertColors ? item->configuration()->indicatorIconInvertedSelectionColor()
    2177            0 :                            : item->configuration()->selectionColor();
    2178            0 :     Color color = item->selected() ? selectionColor : item->configuration()->formattingColor();
    2179            0 :     Pen pen(color);
    2180            0 :     painter->setPen(pen);
    2181            0 :     painter->setFont(item->font());
    2182            0 :     painter->drawSymbol(PointF(), item->iconCode());
    2183            0 : }
    2184              : 
    2185           24 : void TDraw::draw(const LedgerLine* item, Painter* painter, const PaintOptions& opt)
    2186              : {
    2187              :     TRACE_DRAW_ITEM;
    2188              : 
    2189           24 :     if (item->chord()->crossMeasure() == CrossMeasure::SECOND) {
    2190            0 :         return;
    2191              :     }
    2192              : 
    2193           24 :     const LedgerLine::LayoutData* ldata = item->ldata();
    2194              : 
    2195           24 :     painter->setPen(Pen(item->curColor(opt), ldata->lineWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    2196           24 :     if (item->vertical()) {
    2197            0 :         painter->drawLine(LineF(0.0, 0.0, 0.0, item->len()));
    2198              :     } else {
    2199           24 :         painter->drawLine(LineF(0.0, 0.0, item->len(), 0.0));
    2200              :     }
    2201              : }
    2202              : 
    2203            0 : void TDraw::draw(const LetRingSegment* item, Painter* painter, const PaintOptions& opt)
    2204              : {
    2205              :     TRACE_DRAW_ITEM;
    2206            0 :     drawTextLineBaseSegment(item, painter, opt);
    2207            0 : }
    2208              : 
    2209            0 : void TDraw::draw(const Lyrics* item, Painter* painter, const PaintOptions& opt)
    2210              : {
    2211              :     TRACE_DRAW_ITEM;
    2212            0 :     drawTextBase(item, painter, opt);
    2213            0 : }
    2214              : 
    2215            0 : void TDraw::draw(const LyricsLineSegment* item, Painter* painter, const PaintOptions& opt)
    2216              : {
    2217              :     TRACE_DRAW_ITEM;
    2218              : 
    2219            0 :     Pen pen(item->curColor(opt));
    2220            0 :     pen.setWidthF(item->absoluteFromSpatium(item->lineWidth()));
    2221            0 :     pen.setCapStyle(PenCapStyle::FlatCap);
    2222            0 :     painter->setPen(pen);
    2223            0 :     for (const LineF& dash : item->ldata()->dashes()) {
    2224            0 :         painter->drawLine(dash);
    2225              :     }
    2226            0 : }
    2227              : 
    2228            0 : void TDraw::draw(const Marker* item, Painter* painter, const PaintOptions& opt)
    2229              : {
    2230              :     TRACE_DRAW_ITEM;
    2231            0 :     drawTextBase(item, painter, opt);
    2232            0 : }
    2233              : 
    2234            0 : void TDraw::draw(const MeasureNumber* item, Painter* painter, const PaintOptions& opt)
    2235              : {
    2236              :     TRACE_DRAW_ITEM;
    2237            0 :     drawTextBase(item, painter, opt);
    2238            0 : }
    2239              : 
    2240            0 : void TDraw::draw(const MeasureRepeat* item, Painter* painter, const PaintOptions& opt)
    2241              : {
    2242              :     TRACE_DRAW_ITEM;
    2243              : 
    2244            0 :     const MeasureRepeat::LayoutData* ldata = item->ldata();
    2245              : 
    2246            0 :     painter->setPen(item->curColor(opt));
    2247            0 :     item->drawSymbol(ldata->symId, painter);
    2248              : 
    2249            0 :     if (!ldata->numberSym.empty()) {
    2250            0 :         PointF numberPos = item->numberPosition(item->symBbox(ldata->numberSym));
    2251            0 :         item->drawSymbols(ldata->numberSym, painter, numberPos);
    2252              :     }
    2253              : 
    2254            0 :     if (item->style().styleB(Sid::fourMeasureRepeatShowExtenders) && item->numMeasures() == 4) {
    2255            0 :         double hBarThickness = item->style().styleAbsolute(Sid::mmRestHBarThickness);
    2256            0 :         Pen pen(painter->pen());
    2257            0 :         pen.setCapStyle(PenCapStyle::FlatCap);
    2258            0 :         pen.setWidthF(hBarThickness);
    2259            0 :         painter->setPen(pen);
    2260              : 
    2261            0 :         painter->drawLine(ldata->extenderLineLeft);
    2262            0 :         painter->drawLine(ldata->extenderLineRight);
    2263            0 :     }
    2264            0 : }
    2265              : 
    2266            0 : void TDraw::draw(const MMRest* item, Painter* painter, const PaintOptions& opt)
    2267              : {
    2268              :     TRACE_DRAW_ITEM;
    2269            0 :     if (item->shouldNotBeDrawn() || (item->track() % VOICES)) {     //only on voice 1
    2270            0 :         return;
    2271              :     }
    2272              : 
    2273            0 :     const MMRest::LayoutData* ldata = item->ldata();
    2274              : 
    2275            0 :     double _spatium = item->spatium();
    2276              : 
    2277              :     // draw number
    2278            0 :     painter->setPen(item->curColor(opt));
    2279            0 :     RectF numberBox = item->symBbox(ldata->numberSym);
    2280            0 :     PointF numberPos = item->numberPos();
    2281            0 :     if (item->showNumber()) {
    2282            0 :         item->drawSymbols(ldata->numberSym, painter, numberPos);
    2283              :     }
    2284              : 
    2285            0 :     numberBox.translate(numberPos);
    2286              : 
    2287            0 :     if (item->isOldStyle()) {
    2288              :         // draw rest symbols
    2289            0 :         double x = (ldata->restWidth - ldata->symsWidth) * 0.5;
    2290            0 :         double spacing = item->style().styleAbsolute(Sid::mmRestOldStyleSpacing);
    2291            0 :         for (SymId sym : ldata->restSyms) {
    2292            0 :             double y = (sym == SymId::restWhole ? -_spatium : 0);
    2293            0 :             item->drawSymbol(sym, painter, PointF(x, y));
    2294            0 :             x += item->symBbox(sym).width() + spacing;
    2295              :         }
    2296              :     } else {
    2297            0 :         double mag = item->staff()->staffMag(item->tick());
    2298            0 :         Pen pen(painter->pen());
    2299            0 :         pen.setCapStyle(PenCapStyle::FlatCap);
    2300              : 
    2301              :         // draw horizontal line
    2302            0 :         double hBarThickness = item->style().styleAbsolute(Sid::mmRestHBarThickness) * mag;
    2303            0 :         if (hBarThickness) { // don't draw at all if 0, QPainter interprets 0 pen width differently
    2304            0 :             pen.setWidthF(hBarThickness);
    2305            0 :             painter->setPen(pen);
    2306            0 :             double halfHBarThickness = hBarThickness * .5;
    2307            0 :             if (item->showNumber() // avoid painting line through number
    2308            0 :                 && item->style().styleB(Sid::mmRestNumberMaskHBar)
    2309            0 :                 && numberBox.bottom() >= -halfHBarThickness
    2310            0 :                 && numberBox.top() <= halfHBarThickness) {
    2311            0 :                 double gapDistance = (numberBox.width() + _spatium) * .5;
    2312            0 :                 double midpoint = ldata->restWidth * .5;
    2313            0 :                 painter->drawLine(LineF(0.0, 0.0, midpoint - gapDistance, 0.0));
    2314            0 :                 painter->drawLine(LineF(midpoint + gapDistance, 0.0, ldata->restWidth, 0.0));
    2315              :             } else {
    2316            0 :                 painter->drawLine(LineF(0.0, 0.0, ldata->restWidth, 0.0));
    2317              :             }
    2318              :         }
    2319              : 
    2320              :         // draw vertical lines
    2321            0 :         double vStrokeThickness = item->style().styleAbsolute(Sid::mmRestHBarVStrokeThickness) * mag;
    2322            0 :         if (vStrokeThickness) { // don't draw at all if 0, QPainter interprets 0 pen width differently
    2323            0 :             pen.setWidthF(vStrokeThickness);
    2324            0 :             painter->setPen(pen);
    2325            0 :             double halfVStrokeHeight = item->style().styleAbsolute(Sid::mmRestHBarVStrokeHeight) * .5 * mag;
    2326            0 :             painter->drawLine(LineF(0.0, -halfVStrokeHeight, 0.0, halfVStrokeHeight));
    2327            0 :             painter->drawLine(LineF(ldata->restWidth, -halfVStrokeHeight, ldata->restWidth, halfVStrokeHeight));
    2328              :         }
    2329            0 :     }
    2330              : }
    2331              : 
    2332            0 : void TDraw::draw(const MMRestRange* item, Painter* painter, const PaintOptions& opt)
    2333              : {
    2334              :     TRACE_DRAW_ITEM;
    2335            0 :     drawTextBase(item, painter, opt);
    2336            0 : }
    2337              : 
    2338          127 : void TDraw::draw(const Note* item, Painter* painter, const PaintOptions& opt)
    2339              : {
    2340              :     TRACE_DRAW_ITEM;
    2341          127 :     if (item->hidden()) {
    2342            0 :         return;
    2343              :     }
    2344              : 
    2345          127 :     const Note::LayoutData* ldata = item->ldata();
    2346              : 
    2347          127 :     const auto config = item->configuration();
    2348          127 :     const StaffType* staffType = item->staff() ? item->staff()->staffTypeForElement(item) : nullptr;
    2349              : 
    2350          127 :     const bool isTabStaff = staffType && staffType->isTabStaff();
    2351          127 :     const bool negativeFret = isTabStaff && item->negativeFretUsed();
    2352          127 :     const bool useCriticalColor = negativeFret && !item->deadNote() && !opt.isPrinting;
    2353              : 
    2354          127 :     painter->setPen(useCriticalColor ? config->criticalColor() : item->curColor(opt));
    2355              : 
    2356              :     // tablature
    2357          127 :     if (isTabStaff) {
    2358            0 :         if (item->displayFret() == Note::DisplayFretOption::Hide || item->shouldHideFret()) {
    2359            0 :             return;
    2360              :         }
    2361            0 :         const Staff* st = item->staff();
    2362            0 :         const StaffType* tab = st->staffTypeForElement(item);
    2363              : 
    2364            0 :         if (!opt.isPrinting && item->score()->showUnprintable() && (negativeFret || item->fretConflict())) { // fret conflict
    2365            0 :             painter->save();
    2366            0 :             painter->setPen(config->criticalColor());
    2367            0 :             painter->setBrush(config->criticalBackgroundColor());
    2368            0 :             painter->drawRect(ldata->bbox());
    2369            0 :             painter->restore();
    2370              :         }
    2371              : 
    2372            0 :         Font f(tab->fretFont());
    2373            0 :         f.setPointSizeF(f.pointSizeF() * item->magS());
    2374            0 :         painter->setFont(f);
    2375              : 
    2376            0 :         const double startPosX = ldata->bbox().x();
    2377            0 :         const double yOffset = tab->fretFontYOffset();
    2378            0 :         painter->drawText(PointF(startPosX, yOffset * item->magS()), item->fretString());
    2379            0 :     }
    2380              :     // NOT tablature
    2381              :     else {
    2382              :         // skip drawing, if second note of a cross-measure value
    2383          127 :         if (item->chord() && item->chord()->crossMeasure() == CrossMeasure::SECOND) {
    2384            0 :             return;
    2385              :         }
    2386              :         // warn if pitch extends usable range of instrument
    2387              :         // by coloring the notehead
    2388          254 :         if (item->chord() && item->chord()->segment() && item->staff() && !opt.isPrinting
    2389          254 :             && MScore::warnPitchRange && !item->staff()->isDrumStaff(item->chord()->tick())) {
    2390            0 :             const Instrument* in = item->originPart()->instrument(item->chord()->tick());
    2391            0 :             int i = item->ppitch();
    2392            0 :             if (i < in->minPitchP() || i > in->maxPitchP()) {
    2393            0 :                 painter->setPen(item->selected() ? config->criticalSelectedColor() : config->criticalColor());
    2394            0 :             } else if (i < in->minPitchA() || i > in->maxPitchA()) {
    2395            0 :                 painter->setPen(item->selected() ? config->warningSelectedColor() : config->warningColor());
    2396              :             }
    2397              :         }
    2398              :         // Warn if notes are unplayable based on previous harp diagram setting
    2399          254 :         if (item->chord() && item->chord()->segment() && item->staff() && !opt.isPrinting
    2400          254 :             && !item->staff()->isDrumStaff(item->chord()->tick())) {
    2401            0 :             HarpPedalDiagram* prevDiagram = item->originPart()->currentHarpDiagram(item->chord()->segment()->tick());
    2402            0 :             if (prevDiagram && !prevDiagram->isTpcPlayable(item->tpc())) {
    2403            0 :                 painter->setPen(item->selected() ? config->criticalSelectedColor() : config->criticalColor());
    2404              :             }
    2405              :         }
    2406              :         // draw blank notehead to avoid staff and ledger lines
    2407          127 :         if (ldata->cachedSymNull.value() != SymId::noSym) {
    2408            0 :             painter->save();
    2409            0 :             painter->setPen(config->noteBackgroundColor());
    2410            0 :             item->drawSymbol(ldata->cachedSymNull.value(), painter);
    2411            0 :             painter->restore();
    2412              :         }
    2413          127 :         item->drawSymbol(ldata->cachedNoteheadSym.value(), painter);
    2414              :     }
    2415          127 : }
    2416              : 
    2417            0 : void TDraw::draw(const NoteDot* item, Painter* painter, const PaintOptions& opt)
    2418              : {
    2419              :     TRACE_DRAW_ITEM;
    2420            0 :     if (item->note() && item->note()->dotsHidden()) {     // don't draw dot if note is hidden
    2421            0 :         return;
    2422            0 :     } else if (item->rest() && item->rest()->isGap()) {  // don't draw dot for gap rests
    2423            0 :         return;
    2424              :     }
    2425            0 :     const Note* n = item->note();
    2426            0 :     Fraction tick = n ? n->chord()->tick() : item->rest()->tick();
    2427              :     // always draw dot for non-tab
    2428              :     // for tab, draw if on a note and stems through staff or on a rest and rests shown
    2429            0 :     if (!item->staff()->isTabStaff(tick)
    2430            0 :         || (n && item->staff()->staffType(tick)->stemThrough())
    2431            0 :         || (!n && item->staff()->staffType(tick)->showRests())) {
    2432            0 :         painter->setPen(item->curColor(opt));
    2433            0 :         item->drawSymbol(SymId::augmentationDot, painter);
    2434              :     }
    2435              : }
    2436              : 
    2437            0 : void TDraw::draw(const NoteHead* item, Painter* painter, const PaintOptions& opt)
    2438              : {
    2439            0 :     draw(static_cast<const Symbol*>(item), painter, opt);
    2440            0 : }
    2441              : 
    2442            0 : void TDraw::draw(const NoteLineSegment* item, Painter* painter, const PaintOptions& opt)
    2443              : {
    2444              :     TRACE_DRAW_ITEM;
    2445            0 :     drawTextLineBaseSegment(item, painter, opt);
    2446            0 : }
    2447              : 
    2448            0 : void TDraw::draw(const OttavaSegment* item, Painter* painter, const PaintOptions& opt)
    2449              : {
    2450              :     TRACE_DRAW_ITEM;
    2451            0 :     drawTextLineBaseSegment(item, painter, opt);
    2452            0 : }
    2453              : 
    2454            0 : void TDraw::draw(const PageLockIndicator* item, Painter* painter, const PaintOptions& opt)
    2455              : {
    2456              :     TRACE_DRAW_ITEM;
    2457              : 
    2458            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    2459            0 :         return;
    2460              :     }
    2461              : 
    2462            0 :     Color selectionColor = opt.invertColors ? item->configuration()->indicatorIconInvertedSelectionColor()
    2463            0 :                            : item->configuration()->selectionColor();
    2464            0 :     Color color = item->selected() ? selectionColor : item->configuration()->formattingColor();
    2465            0 :     Pen pen(color);
    2466            0 :     painter->setPen(pen);
    2467            0 :     painter->setFont(item->font());
    2468            0 :     painter->drawSymbol(PointF(), item->iconCode());
    2469              : 
    2470            0 :     if (item->selected()) {
    2471            0 :         Color lockedAreaColor = selectionColor;
    2472            0 :         lockedAreaColor.setAlpha(opt.invertColors ? 90 : 38);
    2473            0 :         Brush brush(lockedAreaColor);
    2474            0 :         painter->setBrush(brush);
    2475            0 :         painter->setNoPen();
    2476            0 :         double radius = 0.5 * item->spatium();
    2477              : 
    2478            0 :         PainterPath path;
    2479            0 :         path.setFillRule(PainterPath::FillRule::OddEvenFill);
    2480            0 :         path.addRoundedRect(item->ldata()->rangeRect, radius, radius);
    2481            0 :         path.addRect(item->ldata()->innerRangeRect);
    2482            0 :         painter->drawPath(path);
    2483            0 :     }
    2484            0 : }
    2485              : 
    2486            0 : void TDraw::draw(const Parenthesis* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2487              : {
    2488              :     TRACE_DRAW_ITEM;
    2489              : 
    2490            0 :     EngravingObject* parent = item->ownershipParent();
    2491            0 :     TimeSig* parentTs = parent && parent->isTimeSig() ? toTimeSig(parent) : nullptr;
    2492              : 
    2493            0 :     if (parentTs && !parentTs->showOnThisStaff()) {
    2494            0 :         return;
    2495              :     }
    2496              : 
    2497            0 :     Color penColor = item->curColor(opt);
    2498              : 
    2499            0 :     Pen pen(penColor);
    2500              : 
    2501            0 :     if (item->ldata()->symId != SymId::noSym) {
    2502            0 :         painter->setPen(pen);
    2503            0 :         item->drawSymbol(item->ldata()->symId, painter, PointF(), item->ldata()->symScale);
    2504            0 :         return;
    2505              :     }
    2506              : 
    2507            0 :     painter->setBrush(Brush(pen.color()));
    2508            0 :     pen.setCapStyle(PenCapStyle::RoundCap);
    2509            0 :     pen.setJoinStyle(PenJoinStyle::RoundJoin);
    2510            0 :     pen.setWidthF(item->ldata()->endPointThickness * item->spatium() * item->ldata()->intrinsicMag());
    2511              : 
    2512            0 :     painter->setPen(pen);
    2513            0 :     painter->drawPath(item->ldata()->path());
    2514            0 : }
    2515              : 
    2516            0 : void TDraw::draw(const PartialTieSegment* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2517              : {
    2518            0 :     draw(static_cast<const TieSegment*>(item), painter, opt);
    2519            0 : }
    2520              : 
    2521            0 : void TDraw::draw(const PalmMuteSegment* item, Painter* painter, const PaintOptions& opt)
    2522              : {
    2523              :     TRACE_DRAW_ITEM;
    2524            0 :     drawTextLineBaseSegment(item, painter, opt);
    2525            0 : }
    2526              : 
    2527            0 : void TDraw::draw(const PedalSegment* item, Painter* painter, const PaintOptions& opt)
    2528              : {
    2529              :     TRACE_DRAW_ITEM;
    2530            0 :     drawTextLineBaseSegment(item, painter, opt);
    2531            0 : }
    2532              : 
    2533            0 : void TDraw::draw(const PickScrapeSegment* item, Painter* painter, const PaintOptions& opt)
    2534              : {
    2535              :     TRACE_DRAW_ITEM;
    2536            0 :     drawTextLineBaseSegment(item, painter, opt);
    2537            0 : }
    2538              : 
    2539            0 : void TDraw::draw(const PlayCountText* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2540              : {
    2541              :     TRACE_DRAW_ITEM;
    2542            0 :     drawTextBase(item, painter, opt);
    2543            0 : }
    2544              : 
    2545            0 : void TDraw::draw(const PlayTechAnnotation* item, Painter* painter, const PaintOptions& opt)
    2546              : {
    2547              :     TRACE_DRAW_ITEM;
    2548            0 :     drawTextBase(item, painter, opt);
    2549            0 : }
    2550              : 
    2551            0 : void TDraw::draw(const RasgueadoSegment* item, Painter* painter, const PaintOptions& opt)
    2552              : {
    2553              :     TRACE_DRAW_ITEM;
    2554            0 :     drawTextLineBaseSegment(item, painter, opt);
    2555            0 : }
    2556              : 
    2557            0 : void TDraw::draw(const RehearsalMark* item, Painter* painter, const PaintOptions& opt)
    2558              : {
    2559              :     TRACE_DRAW_ITEM;
    2560            0 :     drawTextBase(item, painter, opt);
    2561            0 : }
    2562              : 
    2563            0 : void TDraw::draw(const Rest* item, Painter* painter, const PaintOptions& opt)
    2564              : {
    2565              :     TRACE_DRAW_ITEM;
    2566              : 
    2567            0 :     if (item->isGap()) {
    2568            0 :         drawDebugGapRest(item, painter);
    2569            0 :         return;
    2570              :     }
    2571              : 
    2572            0 :     if (item->shouldNotBeDrawn()) {
    2573            0 :         return;
    2574              :     }
    2575              : 
    2576            0 :     const Rest::LayoutData* ldata = item->ldata();
    2577              : 
    2578            0 :     painter->setPen(item->curColor(opt));
    2579              : 
    2580            0 :     if (DeadSlapped* ds = item->deadSlapped()) {
    2581            0 :         draw(ds, painter, opt);
    2582              :     } else {
    2583            0 :         item->drawSymbol(ldata->sym, painter);
    2584              :     }
    2585              : }
    2586              : 
    2587            0 : void TDraw::drawDebugGapRest(const Rest* item, muse::draw::Painter* painter)
    2588              : {
    2589            0 :     IF_ASSERT_FAILED(item->debugDrawGap()) {
    2590            0 :         return;
    2591              :     }
    2592              : 
    2593            0 :     painter->setPen(Color::RED);
    2594            0 :     item->drawSymbol(item->ldata()->sym, painter);
    2595              : }
    2596              : 
    2597              : //! NOTE May be removed later (should be only single mode)
    2598            0 : void TDraw::draw(const ShadowNote* item, Painter* painter, const PaintOptions&)
    2599              : {
    2600              :     TRACE_DRAW_ITEM;
    2601              : 
    2602            0 :     if (!item->visible() || !item->isValid()) {
    2603            0 :         return;
    2604              :     }
    2605              : 
    2606            0 :     PointF ap(item->pagePos());
    2607            0 :     painter->translate(ap);
    2608            0 :     double lw = item->style().styleAbsolute(Sid::stemWidth) * item->mag();
    2609            0 :     Pen pen(item->color(), lw, PenStyle::SolidLine, PenCapStyle::FlatCap);
    2610            0 :     painter->setPen(pen);
    2611              : 
    2612            0 :     bool up = item->computeUp();
    2613              : 
    2614              :     // Draw the accidental
    2615            0 :     SymId acc = Accidental::subtype2symbol(item->accidentalType());
    2616            0 :     if (acc != SymId::noSym) {
    2617            0 :         PointF posAcc;
    2618            0 :         posAcc.rx() -= item->symWidth(acc) + item->style().styleAbsolute(Sid::accidentalNoteDistance) * item->mag();
    2619            0 :         item->drawSymbol(acc, painter, posAcc);
    2620              :     }
    2621              : 
    2622              :     // Draw the notehead
    2623            0 :     item->drawSymbol(item->noteheadSymbol(), painter);
    2624              : 
    2625              :     // Draw the dots
    2626            0 :     double sp = item->spatium();
    2627            0 :     double sp2 = sp / 2;
    2628            0 :     double noteheadWidth = item->symWidth(item->noteheadSymbol());
    2629              : 
    2630            0 :     PointF posDot;
    2631            0 :     if (item->duration().dots() > 0) {
    2632            0 :         double d  = item->style().styleAbsolute(Sid::dotNoteDistance) * item->mag();
    2633            0 :         double dd = item->style().styleAbsolute(Sid::dotDotDistance) * item->mag();
    2634            0 :         posDot.rx() += (noteheadWidth + d);
    2635              : 
    2636            0 :         if (item->isRest()) {
    2637            0 :             posDot.ry() += Rest::getDotline(item->duration().type()) * sp2;
    2638              :         } else {
    2639            0 :             posDot.ry() -= (item->lineIndex() % 2 == 0 ? sp2 : 0);
    2640              :         }
    2641              : 
    2642            0 :         if (item->hasFlag() && up) {
    2643            0 :             posDot.rx() = std::max(posDot.x(), noteheadWidth + item->symBbox(item->flagSym()).right());
    2644              :         }
    2645              : 
    2646            0 :         for (int i = 0; i < item->duration().dots(); i++) {
    2647            0 :             posDot.rx() += dd * i;
    2648            0 :             item->drawSymbol(SymId::augmentationDot, painter, posDot);
    2649            0 :             posDot.rx() -= dd * i;
    2650              :         }
    2651              :     }
    2652              : 
    2653              :     // Draw stem and flag
    2654            0 :     if (item->hasStem()) {
    2655            0 :         double x = item->symSmuflAnchor(item->noteheadSymbol(), up ? SmuflAnchorId::stemUpSE : SmuflAnchorId::stemDownNW).x();
    2656            0 :         x += up ? -0.5 * lw : 0.5 * lw;
    2657            0 :         double y1 = item->symSmuflAnchor(item->noteheadSymbol(), up ? SmuflAnchorId::stemUpSE : SmuflAnchorId::stemDownNW).y();
    2658            0 :         double y2 = (up ? -3.5 : 3.5) * sp;
    2659              : 
    2660            0 :         if (item->hasFlag()) {
    2661            0 :             SymId flag = item->flagSym();
    2662            0 :             item->drawSymbol(flag, painter, PointF(x - (lw / 2), y2));
    2663            0 :             y2 += item->symSmuflAnchor(flag, up ? SmuflAnchorId::stemUpNW : SmuflAnchorId::stemDownSW).y();
    2664              :         }
    2665            0 :         painter->drawLine(LineF(x, y1, x, y2));
    2666              :     }
    2667              : 
    2668              :     // Draw ledger lines if needed
    2669            0 :     if (item->ledgerLinesVisible()) {
    2670            0 :         double extraLen = item->style().styleS(Sid::ledgerLineLength).val() * sp;
    2671            0 :         double x1 = -extraLen;
    2672            0 :         double x2 = noteheadWidth + extraLen;
    2673            0 :         double yOffset = item->staffOffsetY();
    2674            0 :         double step = sp2 * item->staffType()->lineDistance().val();
    2675              : 
    2676            0 :         lw = item->style().styleAbsolute(Sid::ledgerLineWidth) * item->mag();
    2677            0 :         pen.setWidthF(lw);
    2678            0 :         painter->setPen(pen);
    2679              : 
    2680            0 :         const int topLine = -2 + yOffset / step;
    2681            0 :         for (int i = topLine; i >= item->lineIndex(); i -= 2) {
    2682            0 :             double y = step * (i - item->lineIndex());
    2683            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2684              :         }
    2685            0 :         int l = item->staffType()->lines() * 2 + yOffset / step; // first ledger line below staff
    2686            0 :         for (int i = l; i <= item->lineIndex(); i += 2) {
    2687            0 :             double y = step * (i - item->lineIndex());
    2688            0 :             painter->drawLine(LineF(x1, y, x2, y));
    2689              :         }
    2690              :     }
    2691              : 
    2692            0 :     item->drawArticulations(painter);
    2693              : 
    2694            0 :     painter->translate(-ap);
    2695            0 : }
    2696              : 
    2697            0 : void TDraw::draw(const SlurSegment* item, Painter* painter, const PaintOptions& opt)
    2698              : {
    2699              :     TRACE_DRAW_ITEM;
    2700              : 
    2701            0 :     painter->save();
    2702            0 :     setMask(item, painter);
    2703              : 
    2704            0 :     Pen pen(item->curColor(opt));
    2705            0 :     double mag = item->staff() ? item->staff()->staffMag(item->slur()->tick()) : 1.0;
    2706              : 
    2707              :     //Replace generic Qt dash patterns with improved equivalents to show true dots (keep in sync with tie.cpp)
    2708            0 :     std::vector<double> dotted     = { 0.01, 1.99 };   // tighter than Qt PenStyle::DotLine equivalent - would be { 0.01, 2.99 }
    2709            0 :     std::vector<double> dashed     = { 3.00, 3.00 };   // Compensating for caps. Qt default PenStyle::DashLine is { 4.0, 2.0 }
    2710            0 :     std::vector<double> wideDashed = { 5.00, 6.00 };
    2711              : 
    2712            0 :     switch (item->slurTie()->styleType()) {
    2713            0 :     case SlurStyleType::Solid:
    2714            0 :         painter->setBrush(Brush(pen.color()));
    2715            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    2716            0 :         pen.setJoinStyle(PenJoinStyle::RoundJoin);
    2717            0 :         pen.setWidthF(item->endWidth() * mag);
    2718            0 :         break;
    2719            0 :     case SlurStyleType::Dotted:
    2720            0 :         painter->setBrush(BrushStyle::NoBrush);
    2721            0 :         pen.setCapStyle(PenCapStyle::RoundCap);           // round dots
    2722            0 :         pen.setDashPattern(dotted);
    2723            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2724            0 :         break;
    2725            0 :     case SlurStyleType::Dashed:
    2726            0 :         painter->setBrush(BrushStyle::NoBrush);
    2727            0 :         pen.setDashPattern(dashed);
    2728            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2729            0 :         break;
    2730            0 :     case SlurStyleType::WideDashed:
    2731            0 :         painter->setBrush(BrushStyle::NoBrush);
    2732            0 :         pen.setDashPattern(wideDashed);
    2733            0 :         pen.setWidthF(item->dottedWidth() * mag);
    2734            0 :         break;
    2735            0 :     case SlurStyleType::Undefined:
    2736            0 :         break;
    2737              :     }
    2738            0 :     painter->setPen(pen);
    2739            0 :     painter->drawPath(item->ldata()->path());
    2740              : 
    2741            0 :     painter->restore();
    2742            0 : }
    2743              : 
    2744            0 : void TDraw::draw(const Spacer* item, Painter* painter, const PaintOptions& opt)
    2745              : {
    2746              :     TRACE_DRAW_ITEM;
    2747            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    2748            0 :         return;
    2749              :     }
    2750              : 
    2751            0 :     auto conf = item->configuration();
    2752              : 
    2753            0 :     Pen pen(item->selected() ? conf->selectionColor() : conf->formattingColor(), item->spatium()* 0.3);
    2754              : 
    2755            0 :     painter->setPen(pen);
    2756            0 :     painter->setBrush(BrushStyle::NoBrush);
    2757            0 :     painter->drawPath(item->ldata()->path);
    2758            0 : }
    2759              : 
    2760           20 : void TDraw::draw(const StaffLines* item, Painter* painter, const PaintOptions& opt)
    2761              : {
    2762              :     TRACE_DRAW_ITEM;
    2763           20 :     painter->save();
    2764              : 
    2765           20 :     setMask(item, painter);
    2766              : 
    2767           20 :     painter->setPen(Pen(item->curColor(opt), item->lw(), PenStyle::SolidLine, PenCapStyle::FlatCap));
    2768           20 :     painter->drawLines(item->lines());
    2769              : 
    2770           20 :     painter->restore();
    2771           20 : }
    2772              : 
    2773            0 : void TDraw::draw(const StaffState* item, Painter* painter, const PaintOptions& opt)
    2774              : {
    2775              :     TRACE_DRAW_ITEM;
    2776            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    2777            0 :         return;
    2778              :     }
    2779              : 
    2780            0 :     const StaffState::LayoutData* ldata = item->ldata();
    2781            0 :     auto conf = item->configuration();
    2782              : 
    2783            0 :     Pen pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2784            0 :             ldata->lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
    2785            0 :     painter->setPen(pen);
    2786            0 :     painter->setBrush(BrushStyle::NoBrush);
    2787            0 :     painter->drawPath(ldata->path);
    2788            0 : }
    2789              : 
    2790            0 : void TDraw::draw(const StaffText* item, Painter* painter, const PaintOptions& opt)
    2791              : {
    2792              :     TRACE_DRAW_ITEM;
    2793              : 
    2794            0 :     drawTextBase(item, painter, opt);
    2795              : 
    2796            0 :     if (item->hasSoundFlag()) {
    2797            0 :         draw(item->soundFlag(), painter, opt);
    2798              :     }
    2799            0 : }
    2800              : 
    2801            0 : void TDraw::draw(const StaveSharingLabel* item, muse::draw::Painter* painter, const PaintOptions& opt)
    2802              : {
    2803              :     TRACE_DRAW_ITEM;
    2804              : 
    2805            0 :     drawTextBase(item, painter, opt);
    2806            0 : }
    2807              : 
    2808            0 : void TDraw::draw(const StaffTypeChange* item, Painter* painter, const PaintOptions& opt)
    2809              : {
    2810              :     TRACE_DRAW_ITEM;
    2811              : 
    2812            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    2813            0 :         return;
    2814              :     }
    2815              : 
    2816            0 :     auto conf = item->configuration();
    2817              : 
    2818            0 :     double _spatium = item->style().spatium();
    2819            0 :     double h  = _spatium * 2.5;
    2820            0 :     double w  = _spatium * 2.5;
    2821            0 :     double lineDist = 0.35;           // line distance for the icon 'staff lines'
    2822              :     // draw icon rectangle
    2823            0 :     painter->setPen(Pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2824            0 :                         item->lw(), PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin));
    2825            0 :     painter->setBrush(BrushStyle::NoBrush);
    2826            0 :     painter->drawRect(0, 0, w, h);
    2827              : 
    2828              :     // draw icon contents
    2829            0 :     int lines = 5;
    2830            0 :     if (item->staffType()) {
    2831            0 :         if (item->staffType()->stemless()) {       // a single notehead represents a stemless staff
    2832            0 :             item->drawSymbol(SymId::noteheadBlack, painter, PointF(w * 0.5 - 0.33 * _spatium, h * 0.5), 0.5);
    2833              :         }
    2834            0 :         if (item->staffType()->invisible()) {      // no lines needed. It's done.
    2835            0 :             return;
    2836              :         }
    2837              :         // show up to 6 lines
    2838            0 :         lines = std::min(item->staffType()->lines(), 6);
    2839              :     }
    2840              :     // calculate starting point Y for the lines from half the icon height (2.5) so staff lines appear vertically centered
    2841            0 :     double startY = 1.25 - (lines - 1) * lineDist * 0.5;
    2842            0 :     painter->setPen(Pen(item->selected() ? conf->selectionColor() : conf->formattingColor(),
    2843            0 :                         2.5, PenStyle::SolidLine, PenCapStyle::SquareCap, PenJoinStyle::MiterJoin));
    2844            0 :     for (int i=0; i < lines; i++) {
    2845            0 :         int y = (startY + i * lineDist) * _spatium;
    2846            0 :         painter->drawLine(0, y, w, y);
    2847              :     }
    2848            0 : }
    2849              : 
    2850           60 : void TDraw::draw(const Stem* item, Painter* painter, const PaintOptions& opt)
    2851              : {
    2852              :     TRACE_DRAW_ITEM;
    2853           60 :     if (!item->chord()) { // may be need assert?
    2854            0 :         return;
    2855              :     }
    2856              : 
    2857              :     // hide if second chord of a cross-measure pair
    2858           60 :     if (item->chord()->crossMeasure() == CrossMeasure::SECOND) {
    2859            0 :         return;
    2860              :     }
    2861              : 
    2862           60 :     const Stem::LayoutData* ldata = item->ldata();
    2863              : 
    2864           60 :     const Staff* staff = item->staff();
    2865           60 :     const StaffType* staffType = staff ? staff->staffTypeForElement(item->chord()) : nullptr;
    2866           60 :     const bool isTablature = staffType && staffType->isTabStaff();
    2867              : 
    2868           60 :     painter->setPen(Pen(item->curColor(opt), item->lineWidthMag(), PenStyle::SolidLine, PenCapStyle::FlatCap));
    2869           60 :     painter->drawLine(ldata->line);
    2870              : 
    2871           60 :     if (!isTablature) {
    2872           60 :         return;
    2873              :     }
    2874              : 
    2875              :     // TODO: adjust bounding rectangle in layout() for dots and for slash
    2876            0 :     double sp = item->spatium();
    2877            0 :     bool isUp = item->up();
    2878              : 
    2879              :     // slashed half note stem
    2880            0 :     if (item->chord()->durationType().type() == DurationType::V_HALF
    2881            0 :         && staffType->minimStyle() == TablatureMinimStyle::SLASHED) {
    2882              :         // position slashes onto stem
    2883            0 :         double y = isUp ? -item->length() + StemLayout::STAFFTYPE_TAB_SLASH_2STARTY_UP * sp
    2884            0 :                    : item->length() - StemLayout::STAFFTYPE_TAB_SLASH_2STARTY_DN * sp;
    2885              :         // if stems through, try to align slashes within or across lines
    2886            0 :         if (staffType->stemThrough()) {
    2887            0 :             double halfLineDist = staffType->lineDistance().val() * sp * 0.5;
    2888            0 :             double halfSlashHgt = StemLayout::STAFFTYPE_TAB_SLASH_2TOTHEIGHT * sp * 0.5;
    2889            0 :             y = lrint((y + halfSlashHgt) / halfLineDist) * halfLineDist - halfSlashHgt;
    2890              :         }
    2891              :         // draw slashes
    2892            0 :         double hlfWdt= sp * StemLayout::STAFFTYPE_TAB_SLASH_WIDTH * 0.5;
    2893            0 :         double sln   = sp * StemLayout::STAFFTYPE_TAB_SLASH_SLANTY;
    2894            0 :         double thk   = sp * StemLayout::STAFFTYPE_TAB_SLASH_THICK;
    2895            0 :         double displ = sp * StemLayout::STAFFTYPE_TAB_SLASH_DISPL;
    2896            0 :         PainterPath path;
    2897            0 :         for (int i = 0; i < 2; ++i) {
    2898            0 :             path.moveTo(hlfWdt, y);                   // top-right corner
    2899            0 :             path.lineTo(hlfWdt, y + thk);             // bottom-right corner
    2900            0 :             path.lineTo(-hlfWdt, y + thk + sln);      // bottom-left corner
    2901            0 :             path.lineTo(-hlfWdt, y + sln);            // top-left corner
    2902            0 :             path.closeSubpath();
    2903            0 :             y += displ;
    2904              :         }
    2905            0 :         painter->setBrush(Brush(item->curColor(opt)));
    2906            0 :         painter->setNoPen();
    2907            0 :         painter->drawPath(path);
    2908            0 :     }
    2909              : 
    2910              :     // dots
    2911              :     // NOT THE BEST PLACE FOR THIS?
    2912              :     // with tablatures and stems beside staves, dots are not drawn near 'notes', but near stems
    2913            0 :     int nDots = item->chord()->dots();
    2914            0 :     if (nDots > 0 && !staffType->stemThrough()) {
    2915            0 :         double x     = item->chord()->dotPosX();
    2916            0 :         double y     = ((StemLayout::STAFFTYPE_TAB_DEFAULTSTEMLEN_DN * 0.2) * sp) * (isUp ? -1.0 : 1.0);
    2917            0 :         double step  = item->style().styleS(Sid::dotDotDistance).val() * sp;
    2918            0 :         for (int dot = 0; dot < nDots; dot++, x += step) {
    2919            0 :             item->drawSymbol(SymId::augmentationDot, painter, PointF(x, y));
    2920              :         }
    2921              :     }
    2922              : }
    2923              : 
    2924            0 : void TDraw::draw(const StemSlash* item, Painter* painter, const PaintOptions& opt)
    2925              : {
    2926              :     TRACE_DRAW_ITEM;
    2927            0 :     const StemSlash::LayoutData* ldata = item->ldata();
    2928            0 :     painter->setPen(Pen(item->curColor(opt), ldata->stemWidth, PenStyle::SolidLine, PenCapStyle::FlatCap));
    2929            0 :     painter->drawLine(ldata->line);
    2930            0 : }
    2931              : 
    2932            0 : void TDraw::draw(const Sticking* item, Painter* painter, const PaintOptions& opt)
    2933              : {
    2934              :     TRACE_DRAW_ITEM;
    2935            0 :     drawTextBase(item, painter, opt);
    2936            0 : }
    2937              : 
    2938            0 : void TDraw::draw(const StringTunings* item, Painter* painter, const PaintOptions& opt)
    2939              : {
    2940              :     TRACE_DRAW_ITEM;
    2941              : 
    2942            0 :     if (item->noStringVisible()) {
    2943            0 :         const TextBase::LayoutData* data = item->ldata();
    2944              : 
    2945            0 :         const double spatium = item->spatium();
    2946            0 :         const double lineWidth = spatium * .15;
    2947              : 
    2948            0 :         const Pen pen(item->curColor(opt), lineWidth, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
    2949            0 :         painter->setPen(pen);
    2950            0 :         painter->setBrush(Brush(item->curColor(opt)));
    2951              : 
    2952            0 :         const RectF rect = data->bbox();
    2953              : 
    2954            0 :         const double x = rect.x();
    2955            0 :         const double y = rect.y();
    2956            0 :         const double width = rect.width();
    2957            0 :         const double height = rect.height();
    2958            0 :         const double topPartHeight = height * .66;
    2959            0 :         const double cornerRadius = height * .1;
    2960              : 
    2961            0 :         PainterPath path;
    2962            0 :         path.moveTo(x, y);
    2963            0 :         path.arcTo(x, y + (topPartHeight - 2 * cornerRadius), 2 * cornerRadius, 2 * cornerRadius, 180.0, 90.0);
    2964            0 :         path.arcTo(x + width - 2 * cornerRadius, y + (topPartHeight - 2 * cornerRadius), 2 * cornerRadius, 2 * cornerRadius, 270, 90);
    2965            0 :         path.lineTo(x + width, y);
    2966            0 :         path.moveTo(x + width / 2, y + topPartHeight);
    2967            0 :         path.lineTo(x + width / 2, y + height);
    2968              : 
    2969            0 :         painter->setBrush(BrushStyle::NoBrush);
    2970            0 :         painter->drawPath(path);
    2971            0 :     } else {
    2972            0 :         drawTextBase(item, painter, opt);
    2973              :     }
    2974            0 : }
    2975              : 
    2976            0 : void TDraw::draw(const Symbol* item, Painter* painter, const PaintOptions& opt)
    2977              : {
    2978              :     TRACE_DRAW_ITEM;
    2979            0 :     bool tabStaff = item->staff() ? item->staff()->isTabStaff(item->tick()) : false;
    2980              : 
    2981            0 :     if (!item->isNoteDot() || !tabStaff) {
    2982            0 :         painter->setPen(item->curColor(opt));
    2983            0 :         if (item->scoreFont()) {
    2984            0 :             item->scoreFont()->draw(item->sym(), painter, item->magS() * item->symbolsSize(), PointF(), item->symAngle());
    2985              :         } else {
    2986            0 :             item->drawSymbol(item->sym(), painter);
    2987              :         }
    2988              :     }
    2989            0 : }
    2990              : 
    2991            0 : void TDraw::draw(const FSymbol* item, Painter* painter, const PaintOptions& opt)
    2992              : {
    2993              :     TRACE_DRAW_ITEM;
    2994              : 
    2995            0 :     painter->setFont(item->font());
    2996            0 :     painter->setPen(item->curColor(opt));
    2997            0 :     painter->drawText(PointF(0, 0), item->toString());
    2998            0 : }
    2999              : 
    3000            0 : void TDraw::draw(const SystemDivider* item, Painter* painter, const PaintOptions& opt)
    3001              : {
    3002            0 :     draw(static_cast<const Symbol*>(item), painter, opt);
    3003            0 : }
    3004              : 
    3005            0 : void TDraw::draw(const SystemText* item, Painter* painter, const PaintOptions& opt)
    3006              : {
    3007            0 :     drawTextBase(item, painter, opt);
    3008            0 : }
    3009              : 
    3010            0 : void TDraw::draw(const IndicatorIcon* item, muse::draw::Painter* painter, const PaintOptions& opt)
    3011              : {
    3012              :     TRACE_DRAW_ITEM;
    3013              : 
    3014            0 :     if (opt.isPrinting || !item->score()->showUnprintable()) {
    3015            0 :         return;
    3016              :     }
    3017              : 
    3018            0 :     Color selectionColor = opt.invertColors ? item->configuration()->indicatorIconInvertedSelectionColor()
    3019            0 :                            : item->configuration()->selectionColor();
    3020            0 :     Color color = item->selected() ? selectionColor : item->configuration()->formattingColor();
    3021            0 :     Pen pen(color);
    3022            0 :     painter->setPen(pen);
    3023            0 :     painter->setFont(item->font());
    3024            0 :     painter->drawSymbol(PointF(), item->iconCode());
    3025              : 
    3026            0 :     if (item->isSystemLockIndicator() && item->selected()) {
    3027            0 :         const SystemLockIndicator* sli = toSystemLockIndicator(item);
    3028              : 
    3029            0 :         Color lockedAreaColor = selectionColor;
    3030            0 :         lockedAreaColor.setAlpha(opt.invertColors ? 90 : 38);
    3031            0 :         Brush brush(lockedAreaColor);
    3032            0 :         painter->setBrush(brush);
    3033            0 :         painter->setNoPen();
    3034            0 :         double radius = 0.5 * sli->spatium();
    3035              : 
    3036            0 :         painter->drawRoundedRect(sli->ldata()->rangeRect, radius, radius);
    3037            0 :     }
    3038            0 : }
    3039              : 
    3040            0 : void TDraw::draw(const SoundFlag* item, Painter* painter, const PaintOptions& opt)
    3041              : {
    3042              :     TRACE_DRAW_ITEM;
    3043              : 
    3044            0 :     if (item->shouldHide()) {
    3045            0 :         return;
    3046              :     }
    3047              : 
    3048            0 :     painter->setNoPen();
    3049            0 :     painter->setBrush(item->iconBackgroundColor());
    3050            0 :     painter->drawEllipse(item->ldata()->bbox().adjusted(-4.0, -4.0, 4.0, 4.0));
    3051              : 
    3052            0 :     painter->setFont(item->iconFont());
    3053            0 :     painter->setPen(!item->selected() ? item->curColor(true, opt) : Color::WHITE);
    3054            0 :     painter->drawText(item->ldata()->bbox(), muse::draw::AlignCenter, muse::draw::TextDontClip, Char(item->iconCode()));
    3055              : }
    3056              : 
    3057            0 : void TDraw::draw(const TabDurationSymbol* item, Painter* painter, const PaintOptions& opt)
    3058              : {
    3059              :     TRACE_DRAW_ITEM;
    3060              : 
    3061            0 :     if (!item->tab()) {
    3062            0 :         return;
    3063              :     }
    3064              : 
    3065            0 :     const TabDurationSymbol::LayoutData* ldata = item->ldata();
    3066              : 
    3067            0 :     if (item->isRepeat() && (item->tab()->symRepeat() == TablatureSymbolRepeat::SYSTEM)) {
    3068            0 :         Chord* chord = toChord(item->ownershipParent());
    3069            0 :         ChordRest* prevCR = Navigation::prevChordRest(chord);
    3070            0 :         if (prevCR && (chord->measure()->system() == prevCR->measure()->system())) {
    3071            0 :             return;
    3072              :         }
    3073              :     }
    3074              : 
    3075            0 :     double mag = item->magS();
    3076            0 :     double imag = 1.0 / mag;
    3077              : 
    3078            0 :     Pen pen(item->curColor(opt));
    3079            0 :     painter->setPen(pen);
    3080            0 :     painter->scale(mag, mag);
    3081            0 :     if (ldata->beamGrid == TabBeamGrid::NONE) {
    3082              :         // if no beam grid, draw symbol
    3083            0 :         painter->setFont(item->tab()->durationFont());
    3084            0 :         painter->drawText(PointF(0.0, 0.0), item->text());
    3085              :     } else {
    3086              :         // if beam grid, draw stem line
    3087            0 :         const TablatureDurationFont& font = item->tab()->tabDurationFont();
    3088            0 :         double _spatium = item->spatium();
    3089            0 :         pen.setCapStyle(PenCapStyle::FlatCap);
    3090            0 :         pen.setWidthF(font.gridStemWidth.toAbsolute(_spatium));
    3091            0 :         painter->setPen(pen);
    3092              :         // take stem height from bbox, but de-magnify it, as drawing is already magnified
    3093            0 :         double h = ldata->bbox().y() / mag;
    3094            0 :         painter->drawLine(PointF(0.0, h), PointF(0.0, 0.0));
    3095              :         // if beam grid is medial/final, draw beam lines too: lines go from mid of
    3096              :         // previous stem (delta x stored in _beamLength) to mid of this' stem (0.0)
    3097            0 :         if (ldata->beamGrid == TabBeamGrid::MEDIALFINAL) {
    3098            0 :             pen.setWidthF(font.gridBeamWidth.toAbsolute(_spatium));
    3099            0 :             painter->setPen(pen);
    3100              :             // lower height available to beams by half a beam width,
    3101              :             // so that top beam upper border aligns with stem top
    3102            0 :             h += (font.gridBeamWidth.toAbsolute(_spatium)) * 0.5;
    3103              :             // draw beams equally spaced within the stem height (this is
    3104              :             // different from modern engraving, but common in historic prints)
    3105            0 :             double step  = -h / ldata->beamLevel;
    3106            0 :             double y     = h;
    3107            0 :             for (int i = 0; i < ldata->beamLevel; i++, y += step) {
    3108            0 :                 painter->drawLine(PointF(ldata->beamLength, y), PointF(0.0, y));
    3109              :             }
    3110              :         }
    3111              :     }
    3112            0 :     painter->scale(imag, imag);
    3113            0 : }
    3114              : 
    3115            0 : void TDraw::draw(const Tapping* item, muse::draw::Painter* painter, const PaintOptions& opt)
    3116              : {
    3117            0 :     painter->setPen(item->curColor(opt));
    3118            0 :     if (item->ldata()->symId != SymId::noSym) {
    3119            0 :         item->drawSymbol(item->ldata()->symId, painter);
    3120            0 :     } else if (TappingText* text = item->text()) {
    3121            0 :         painter->translate(text->pos());
    3122            0 :         drawTextBase(text, painter, opt);
    3123            0 :         painter->translate(-text->pos());
    3124              :     } else {
    3125            0 :         assert(false && "Drawing Tapping item without text or symbol");
    3126              :     }
    3127            0 : }
    3128              : 
    3129            0 : void TDraw::draw(const TempoText* item, Painter* painter, const PaintOptions& opt)
    3130              : {
    3131              :     TRACE_DRAW_ITEM;
    3132            0 :     drawTextBase(item, painter, opt);
    3133            0 : }
    3134              : 
    3135            0 : void TDraw::draw(const Text* item, Painter* painter, const PaintOptions& opt)
    3136              : {
    3137              :     TRACE_DRAW_ITEM;
    3138            0 :     drawTextBase(item, painter, opt);
    3139            0 : }
    3140              : 
    3141            0 : void TDraw::draw(const TextLineSegment* item, Painter* painter, const PaintOptions& opt)
    3142              : {
    3143              :     TRACE_DRAW_ITEM;
    3144            0 :     drawTextLineBaseSegment(item, painter, opt);
    3145            0 : }
    3146              : 
    3147            0 : void TDraw::draw(const TieSegment* item, Painter* painter, const PaintOptions& opt)
    3148              : {
    3149              :     TRACE_DRAW_ITEM;
    3150              : 
    3151              :     // hide tie toward the second chord of a cross-measure value
    3152            0 :     if (item->tie()->endNote() && item->tie()->endNote()->chord()->crossMeasure() == CrossMeasure::SECOND) {
    3153            0 :         return;
    3154              :     }
    3155              : 
    3156            0 :     painter->save();
    3157              : 
    3158            0 :     setMask(item, painter);
    3159              : 
    3160            0 :     Color penColor = item->curColor(item->getProperty(Pid::VISIBLE).toBool(), item->getProperty(Pid::COLOR).value<Color>(), opt);
    3161            0 :     if (!opt.isPrinting && item->ldata()->allJumpPointsInactive) {
    3162            0 :         penColor.setAlpha(std::min(penColor.alpha(), 85));
    3163              :     }
    3164              : 
    3165            0 :     Pen pen(penColor);
    3166            0 :     double mag = item->staff() ? item->staff()->staffMag(item->tie()->tick()) : 1.0;
    3167              :     //Replace generic Qt dash patterns with improved equivalents to show true dots (keep in sync with slur.cpp)
    3168            0 :     std::vector<double> dotted     = { 0.01, 1.99 };   // tighter than Qt PenStyle::DotLine equivalent - would be { 0.01, 2.99 }
    3169            0 :     std::vector<double> dashed     = { 3.00, 3.00 };   // Compensating for caps. Qt default PenStyle::DashLine is { 4.0, 2.0 }
    3170            0 :     std::vector<double> wideDashed = { 5.00, 6.00 };
    3171              : 
    3172            0 :     switch (item->slurTie()->styleType()) {
    3173            0 :     case SlurStyleType::Solid:
    3174            0 :         painter->setBrush(Brush(pen.color()));
    3175            0 :         pen.setCapStyle(PenCapStyle::RoundCap);
    3176            0 :         pen.setJoinStyle(PenJoinStyle::RoundJoin);
    3177            0 :         pen.setWidthF(item->endWidth() * mag);
    3178            0 :         break;
    3179            0 :     case SlurStyleType::Dotted:
    3180            0 :         painter->setBrush(BrushStyle::NoBrush);
    3181            0 :         pen.setCapStyle(PenCapStyle::RoundCap);           // True dots
    3182            0 :         pen.setDashPattern(dotted);
    3183            0 :         pen.setWidthF(item->dottedWidth() * mag);
    3184            0 :         break;
    3185            0 :     case SlurStyleType::Dashed:
    3186            0 :         painter->setBrush(BrushStyle::NoBrush);
    3187            0 :         pen.setDashPattern(dashed);
    3188            0 :         pen.setWidthF(item->dottedWidth() * mag);
    3189            0 :         break;
    3190            0 :     case SlurStyleType::WideDashed:
    3191            0 :         painter->setBrush(BrushStyle::NoBrush);
    3192            0 :         pen.setDashPattern(wideDashed);
    3193            0 :         pen.setWidthF(item->dottedWidth() * mag);
    3194            0 :         break;
    3195            0 :     case SlurStyleType::Undefined:
    3196            0 :         break;
    3197              :     }
    3198            0 :     painter->setPen(pen);
    3199            0 :     painter->drawPath(item->ldata()->path());
    3200              : 
    3201            0 :     painter->restore();
    3202            0 : }
    3203              : 
    3204           10 : void TDraw::draw(const TimeSig* item, Painter* painter, const PaintOptions& opt)
    3205              : {
    3206              :     TRACE_DRAW_ITEM;
    3207              : 
    3208           10 :     if (item->staff() && !const_cast<const Staff*>(item->staff())->staffType(item->tick())->genTimesig()) {
    3209            0 :         return;
    3210              :     }
    3211           10 :     if (!item->showOnThisStaff()) {
    3212            0 :         return;
    3213              :     }
    3214           10 :     painter->setPen(item->curColor(opt));
    3215              : 
    3216           10 :     const TimeSig::LayoutData* ldata = item->ldata();
    3217              : 
    3218           10 :     item->drawSymbols(ldata->ns, painter, ldata->pz, item->scale());
    3219           10 :     item->drawSymbols(ldata->ds, painter, ldata->pn, item->scale());
    3220              : 
    3221           10 :     if (item->largeParentheses()) {
    3222            0 :         item->drawSymbol(SymId::timeSigParensLeft,  painter, ldata->pointLargeLeftParen,  item->scale().width());
    3223            0 :         item->drawSymbol(SymId::timeSigParensRight, painter, ldata->pointLargeRightParen, item->scale().width());
    3224              :     }
    3225              : }
    3226              : 
    3227            0 : void TDraw::draw(const TimeTickAnchor* item, Painter* painter, const PaintOptions& opt)
    3228              : {
    3229            0 :     if (opt.isPrinting) {
    3230            0 :         return;
    3231              :     }
    3232              : 
    3233            0 :     TimeTickAnchor::DrawRegion drawRegion = item->drawRegion();
    3234              : 
    3235            0 :     if (drawRegion == TimeTickAnchor::DrawRegion::OUT_OF_RANGE) {
    3236            0 :         return;
    3237              :     }
    3238              : 
    3239            0 :     Color voiceColor = item->configuration()->voiceColor(item->voiceIdx());
    3240              : 
    3241              :     static constexpr double TINT_MAIN_DARKER = 0.45;
    3242              :     static constexpr double TINT_MAIN_LIGHTER = 0.55;
    3243              :     static constexpr double TINT_EXTENDED_DARKER = 0.75;
    3244              :     static constexpr double TINT_EXTENDED_LIGHTER = 0.85;
    3245              : 
    3246              :     double tint = drawRegion == TimeTickAnchor::DrawRegion::MAIN_REGION
    3247            0 :                   ? item->ldata()->darker() ? TINT_MAIN_DARKER : TINT_MAIN_LIGHTER
    3248            0 :                   : item->ldata()->darker() ? TINT_EXTENDED_DARKER : TINT_EXTENDED_LIGHTER;
    3249              : 
    3250            0 :     voiceColor.applyTint(tint);
    3251              : 
    3252            0 :     Brush brush;
    3253            0 :     brush.setColor(voiceColor);
    3254            0 :     brush.setStyle(BrushStyle::SolidPattern);
    3255            0 :     painter->setBrush(brush);
    3256            0 :     painter->setNoPen();
    3257              : 
    3258            0 :     painter->drawRect(item->ldata()->bbox());
    3259            0 : }
    3260              : 
    3261            0 : void TDraw::draw(const TremoloSingleChord* item, Painter* painter, const PaintOptions& opt)
    3262              : {
    3263              :     TRACE_DRAW_ITEM;
    3264              : 
    3265            0 :     if (item->isBuzzRoll()) {
    3266            0 :         painter->setPen(item->curColor(opt));
    3267            0 :         item->drawSymbol(SymId::buzzRoll, painter);
    3268              :     } else {
    3269            0 :         painter->setBrush(Brush(item->curColor(opt)));
    3270            0 :         painter->setNoPen();
    3271            0 :         painter->drawPath(item->path());
    3272              :     }
    3273            0 : }
    3274              : 
    3275            0 : void TDraw::draw(const TremoloTwoChord* item, Painter* painter, const PaintOptions& opt)
    3276              : {
    3277              :     TRACE_DRAW_ITEM;
    3278              : 
    3279            0 :     const TremoloTwoChord::LayoutData* ldata = item->ldata();
    3280              : 
    3281            0 :     if (!item->beamSegments().empty()) {
    3282              :         // two-note trems act like beams
    3283              : 
    3284              :         // make beam thickness independent of slant
    3285              :         // (expression can be simplified?)
    3286            0 :         const LineF bs = item->beamSegments().front()->line;
    3287            0 :         double d = (std::abs(bs.y2() - bs.y1())) / (bs.x2() - bs.x1());
    3288            0 :         if (item->beamSegments().size() > 1 && d > M_PI / 6.0) {
    3289            0 :             d = M_PI / 6.0;
    3290              :         }
    3291            0 :         double ww = (ldata->beamWidth / 2.0) / sin(M_PI_2 - atan(d));
    3292            0 :         painter->setBrush(Brush(item->curColor(opt)));
    3293            0 :         painter->setNoPen();
    3294            0 :         for (const BeamSegment* bs1 : item->beamSegments()) {
    3295            0 :             painter->drawPolygon(
    3296            0 :                 PolygonF({
    3297            0 :                 PointF(bs1->line.x1(), bs1->line.y1() - ww),
    3298            0 :                 PointF(bs1->line.x2(), bs1->line.y2() - ww),
    3299            0 :                 PointF(bs1->line.x2(), bs1->line.y2() + ww),
    3300            0 :                 PointF(bs1->line.x1(), bs1->line.y1() + ww),
    3301            0 :             }),
    3302              :                 FillRule::OddEvenFill);
    3303              :         }
    3304              :     }
    3305            0 : }
    3306              : 
    3307            0 : void TDraw::draw(const TremoloBar* item, Painter* painter, const PaintOptions& opt)
    3308              : {
    3309              :     TRACE_DRAW_ITEM;
    3310            0 :     const TremoloBar::LayoutData* ldata = item->ldata();
    3311            0 :     const double lw = item->absoluteFromSpatium(item->lineWidth());
    3312            0 :     Pen pen(item->curColor(opt), lw, PenStyle::SolidLine, PenCapStyle::RoundCap, PenJoinStyle::RoundJoin);
    3313            0 :     painter->setPen(pen);
    3314            0 :     painter->drawPolyline(ldata->polygon);
    3315            0 : }
    3316              : 
    3317            0 : void TDraw::draw(const TrillSegment* item, Painter* painter, const PaintOptions& opt)
    3318              : {
    3319              :     TRACE_DRAW_ITEM;
    3320            0 :     painter->setPen(item->spanner()->curColor(opt));
    3321            0 :     item->drawSymbols(item->symbols(), painter);
    3322            0 : }
    3323              : 
    3324            0 : void TDraw::draw(const TripletFeel* item, Painter* painter, const PaintOptions& opt)
    3325              : {
    3326              :     TRACE_DRAW_ITEM;
    3327            0 :     drawTextBase(item, painter, opt);
    3328            0 : }
    3329              : 
    3330            0 : void TDraw::draw(const Tuplet* item, Painter* painter, const PaintOptions& opt)
    3331              : {
    3332              :     TRACE_DRAW_ITEM;
    3333              : 
    3334              :     // if in a TAB without stems, tuplets are not shown
    3335            0 :     const StaffType* stt = item->staffType();
    3336            0 :     if (stt && stt->isTabStaff() && stt->stemless()) {
    3337            0 :         return;
    3338              :     }
    3339              : 
    3340            0 :     Color color(item->curColor(opt));
    3341            0 :     if (item->number()) {
    3342            0 :         painter->setPen(color);
    3343            0 :         PointF pos(item->number()->pos());
    3344            0 :         painter->translate(pos);
    3345            0 :         draw(item->number(), painter, opt);
    3346            0 :         painter->translate(-pos);
    3347              :     }
    3348            0 :     if (item->hasBracket()) {
    3349            0 :         Pen pen(color, item->absoluteFromSpatium(item->bracketWidth()));
    3350            0 :         pen.setJoinStyle(PenJoinStyle::MiterJoin);
    3351            0 :         pen.setCapStyle(PenCapStyle::FlatCap);
    3352            0 :         painter->setPen(pen);
    3353            0 :         if (!item->number()) {
    3354            0 :             painter->drawPolyline(item->bracketL, 4);
    3355              :         } else {
    3356            0 :             painter->drawPolyline(item->bracketL, 3);
    3357            0 :             painter->drawPolyline(item->bracketR, 3);
    3358              :         }
    3359            0 :     }
    3360              : }
    3361              : 
    3362            0 : void TDraw::draw(const VibratoSegment* item, Painter* painter, const PaintOptions& opt)
    3363              : {
    3364              :     TRACE_DRAW_ITEM;
    3365            0 :     painter->setPen(item->spanner()->curColor(opt));
    3366            0 :     item->drawSymbols(item->symbols(), painter);
    3367            0 : }
    3368              : 
    3369            0 : void TDraw::draw(const VoltaSegment* item, Painter* painter, const PaintOptions& opt)
    3370              : {
    3371              :     TRACE_DRAW_ITEM;
    3372            0 :     drawTextLineBaseSegment(item, painter, opt);
    3373            0 : }
    3374              : 
    3375            0 : void TDraw::draw(const WhammyBarSegment* item, Painter* painter, const PaintOptions& opt)
    3376              : {
    3377              :     TRACE_DRAW_ITEM;
    3378            0 :     drawTextLineBaseSegment(item, painter, opt);
    3379            0 : }
    3380              : 
    3381           50 : void TDraw::setMask(const EngravingItem* item, Painter* painter)
    3382              : {
    3383           50 :     const EngravingItem::LayoutData* ldata = item->ldata();
    3384              : 
    3385           50 :     const Shape& mask = ldata->mask();
    3386           50 :     if (mask.empty()) {
    3387           50 :         return;
    3388              :     }
    3389              : 
    3390            0 :     RectF background = ldata->bbox().padded(item->spatium());
    3391              : 
    3392            0 :     painter->setMask(background, mask.toRects());
    3393              : }
        

Generated by: LCOV version 2.0-1