From 8ec64c8cf3e94c417921c5c851e9b83ecaeb90f6 Mon Sep 17 00:00:00 2001 From: Cameron White Date: Sat, 2 Aug 2014 01:36:24 -0400 Subject: [PATCH] Render triplet feel types for tempo markers. - In order to make the triplet feel symbols legible, I bumped up the vertical spacing for system symbols and attempted to crop the images as tightly as possible. - Fixed several layout issues with rehearsal signs, text items, chords, and tempo markers so that they are aligned correctly with the new symbol spacing. Bug: #44 --- source/images/triplet_feel_eighth.png | Bin 1062 -> 1239 bytes source/images/triplet_feel_eighth_off.png | Bin 1011 -> 1239 bytes source/images/triplet_feel_sixteenth.png | Bin 903 -> 1038 bytes source/images/triplet_feel_sixteenth_off.png | Bin 959 -> 1097 bytes source/painters/layoutinfo.cpp | 2 +- source/painters/systemrenderer.cpp | 84 ++++++++++++++----- 6 files changed, 63 insertions(+), 23 deletions(-) diff --git a/source/images/triplet_feel_eighth.png b/source/images/triplet_feel_eighth.png index 34cde95c34cf4d66b54dfca76922e00542cee09d..ee64d982b1013f567db3f4b37d7176059943590b 100644 GIT binary patch literal 1239 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 literal 1011 zcmVx{3m+heASQ^S zDA-ttrHz8vN-Weu5F%IvF`e3Ij5ZntK_&PiL83@7;#%Ch?6{fT?43DhW;b&`xa{Vh z$$$R6XXozB&YcC1$CDmyz#|}U+k43nDQ59~AR@s-OYr0sa7sQuZ<_$(OXX zA=^yBOi!DDYj(Q}K(2z0CnBW-xhiCvO@a6ra2m6xRMPQ8q?!So1+)W)fiAoKJz#o7 zJx>Lq3}A=-pCdwglZw)*Ly8vQ1kf51dtx6qDCN#H<=)ZDZGRu*&&p5PScik2r%K8V zU=FxSu_$LT1?aMUgTOooJx`TX8o)+O5ncth8v?EaizDcHJf6&xn|KqCMPn)*H~w)C zd!^_6g5DlM&ALMCJR~k#(>73noIq1UYY+KE?Oni$Dnx-M|gtHD+N@}SJs~L?+EATRqzfwz5OI29SXiSdr z|6+_QcG3XRj&{8>p@BI+`-ofur47jRbdysVUoRL z>SC3?hJeipYN-ml=*@O9DnK*vZ~|ZVfu#v+sS2wZ6`~P1WIcYwyfIz?S1`YXmzI{Q hu$obi$K&y&%0He6S=QT6VI%+m002ovPDHLkV1fcH#0mfa diff --git a/source/images/triplet_feel_sixteenth.png b/source/images/triplet_feel_sixteenth.png index 41d7fa2b972a1280da02b9e82b34999f59d36506..b78ad5bdde29cbcf62323a0ef2cea533c73c16ae 100644 GIT binary patch literal 1038 zcmeAS@N?(olHy`uVBq!ia0vp^@jz_D!3HE5bkZ1sBx7-qyA#8@b22Z19F}xPUq=Rp zjs4tz5?O(K&H|6fVg?4G5)fv*mnL5U6cj6QjVKAuPb(=;EJ|f4NX*PD(aTFMQ83Xn zuzvA1lYxP`(bL5-q$2L^9N!Z@i4twc?Ohl4E7@~LZxm2X%{?0Cb+WBjX`0xkEkQTB zc&%L{U!1<=_s{HK*rZn0lZTj&*7|>baprdQxyti%s^^`#UVK&5xOm_1y5}=L_s*PL z%;xxEe=&z$W4&8lgZM)(37?6JCotFZpFe!LpswV;><$*T-~`ntasMROJ(pFUc5wLw z{R3wA1YbP-aNg47wEWPNrxWrGe?QjjVECZ?~0(a3mh3$4@YtL9}xZ^_T(G?1FacChu_7WSSwsGDzJph6 z+=PXB5r0&Qc|RHMV-Qzp&wc-M{sS4Gm8ZFlOnAH7`7J(Nzp(8$Q~sf|2JXRe0xSoe z4%~Y_rE22quoq=}?8EPc>lfYSy4&|PdLdJ480Ray)2ro5W^0{NUvNgt@oswMyTjX+ zYcmb=!=ILYD-Zg6dDEU3m(yRHO>;W!J^%I<5ANP|NAKL*v?t)(+tz8%?P`|BeR;Wh zow;dSyu~=`0GvYTsUaDf%ECDPOJ5zsSCe9x>~DR`7txSW!L%Yzn2beThsbsoAKuA ze{23XYr99@m?nDIKR~QXKkn}Hy>*#j<@a7sM-?co{FJ|~?GvZQX0L$nSD)VekpAmK zlT_*an!kVK)7l^A{$Q(X&VOiIAyB3n0&;tCto`|8)vUT(PMU$89do^&>ys4o&JS~Z z!A9&{_g~^nt65~b(Q1~``LBO%Kk(i_{8kDdIKbb3{l9yjk9cKW7L3n-?_f;EDk9OU+wWadBmoD=Yu&l_IFrcg9GyQr0=5N z{;^d{K06d#sr85PMhnQ+`00B}H<<5fx|cjd+fe?{+6}x=%lRKxE;+8)ZSS;ilm5fd p6Q|=!9l;S+{rBJ(37&sUn{8h{m^}MWAuzi#c)I$ztaD0e0stYl{b2wA literal 903 zcmV;219<$2P)A#|_4GtV5fv0aifcts;our;ZM;?lL2TScQM9!1 zKTr@`xofl&R4hca6B{`{8ow$PK?@f-!LK`9i^<}eO|mm{Z)TF+_kobT$>cY`&6|0X z*~|qLMNxb?2s{Eh$?^`k0IZ5>YE(Ib3Bp_89MA&pCuP@xW;|=7#{{M~dTrSvcc+yjGU;J8#yMQcfhjhExo_%kn4d`!3tR_K=F90VxOXo}vK>%fPg* z0Vx;fo}vK>Phl_7fP|;8*Jwa0M%@B(gZ^29Ma!)?HvOqvK!zU4(RB!|wPa7>%;P8U zZ5i#kBCY3bLh2`v(9>w7+q2QryR3>)7_hqi2bFZnib3}|QE7xsS<-h|F;W&3WF}2n zaadobxL(xV_15HV&>j+pA9))zAaTf@f1m*ggY`gB0}>W}KvfaabJlXP3CI|57?=ZI z0bhaFz)j$QqcKUX8104j-^VoY0=q$2NUhM`WBBjmBxYK@?Wj1ER%q`r{P%Ixq47Z` zB(*|&kKwNaP&3oBL+=0p002ovPDHLkV1m(=o}mB$ diff --git a/source/images/triplet_feel_sixteenth_off.png b/source/images/triplet_feel_sixteenth_off.png index 9cf7826ec81c6f2f0d45324d40c2f9efe206aa1e..85b89841187eb09f88ae1cf8a31ebb27fbaa6a7e 100644 GIT binary patch literal 1097 zcmV-P1h)H$P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&02XvbSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8JLvUk000BLNkl3A=AJvZnYqIJ<`8@e{|@~KFT!Q8kddR11OEWe!_)Bb@Uc5^5iDe2Ipkjc z1+L=*Lzcj2kQ-ndA1LVI@Xtc-{VrD^hregAR2Ulz;UoA5ZsG%lbhrms-3eWmLLOrF z!5fh4U4jds;pP+~aEG=7x^U?B{BL*;@*Pm6nn4Q@#0+ZlS5IHFpbodZ>Pfe8qwGnUHG(?a^2+cd=o9V^crmm* zdu|dN!D_HGuWk)ouFCc7ds6*sSy@nq?}e7Tt`OhT$tvW{sc@x4bg^2-M+jUKxG^>ToyD9sW2rhO(!&etMxSl(glQ;a5-= zO4{;ReC`dP?8(iN)~_s-wB_X0%DQ1)b5S?X67 zO4NBNC~N4I#a|4E;cfU9euwYiJ$Mjy4Oi!-psXQVKfIFgHMD>xV^HU%psXQVKc^t? zkKhaP*@ikV1!WD{`Z)%D0Zlfc&PzdAL$-dlz#q^T&}0a8UJA+@vi4*5!s#Nftqq~h zOF>yf)_&eYUqF+*sYQsCykC%~i&ZFlQqQNxPv{E>`4aM?h7euzc(pq3QldoJlX^Zi zUO-=nPagYr!6v%oeSrjUo==U-&==&&%lHq#HoD|V&T)HC_N1Oq4c`6l3G@Y; z58+lAgE}t-WewT;;We(VP)dK}3_J!70$YKP4#$sZFabOOR)FoEy^JKi)Ur2Yo7JfHGy_~u zwz~|p3Unftq$hGZW1E?Q_m_e5s7fi)iCCgDft!Fi;3P1gY=0M6YpEA0z-9tF$={q3 z(ij6h&k2QIp=sn5$MTXDH&n5454D=$Jc zK3Vq}*kYg;(WGbs+o&YG9@y?1a0A$3p%;lnB9X9Ym2XmrtA0NP{C1>WhKrcA=h@YH zNL5yR8}NnH<@c(U)~EmJ{41na1&Nr9t1Z+D8C!fNB>f4@s#dAWv!OpXX%DT`GBNNo z8LvjTykl5Kx}5iWagk3i_1Yr)#I@{qBSK0@Xn5I=#eGO%_^gnu9vf2C#G|Z8xCsfV zQfejCgyiA#Fj#_8|Dh*j>?$Sngk&+&Rno+SG`(sH{WmcoBTZRCLT(SY8GhoiXj$-M z(~Po&G`&4E4yika()UAj^wyL8IBFihfFHsh>eSL6P_l}2^jrrg8B>;4Jjx1;LjOK5 zF51$+FX5_Xxu);m2|ijDsLFPAl;yf*K|yC~V#@;9=-WU=ocZ@vA?pOkwDnL$%b9=V@M;^s_TGA8Ny86v$8xu^MeUEm1n zIJ^iGy=hb+(n!W6JwK&P0*@%p{C!}TCp{Y^J$Q+y4V*{@{)GC%n3up+)YtX-*0Vv< hLkRIiB9TZ4`~z?$UQrmBdI|sl002ovPDHLkV1fgfz)AoB diff --git a/source/painters/layoutinfo.cpp b/source/painters/layoutinfo.cpp index 2334b73f4..ae12708de 100644 --- a/source/painters/layoutinfo.cpp +++ b/source/painters/layoutinfo.cpp @@ -35,7 +35,7 @@ const double LayoutInfo::STAFF_BORDER_SPACING = 12; const double LayoutInfo::CLEF_PADDING = 3; const double LayoutInfo::ACCIDENTAL_WIDTH = 6; const double LayoutInfo::CLEF_WIDTH = 22; -const double LayoutInfo::SYSTEM_SYMBOL_SPACING = 18; +const double LayoutInfo::SYSTEM_SYMBOL_SPACING = 22; const double LayoutInfo::MIN_POSITION_SPACING = 3; const double LayoutInfo::TAB_SYMBOL_SPACING = 10; const double LayoutInfo::DEFAULT_POSITION_SPACING = 20; diff --git a/source/painters/systemrenderer.cpp b/source/painters/systemrenderer.cpp index fb30ace25..248819d60 100644 --- a/source/painters/systemrenderer.cpp +++ b/source/painters/systemrenderer.cpp @@ -42,6 +42,13 @@ #include #include +static inline void centerSymbolVertically(QGraphicsItem &item, double x, + double y_top) +{ + item.setPos(x, y_top + 0.5 * (LayoutInfo::SYSTEM_SYMBOL_SPACING - + item.boundingRect().height())); +} + SystemRenderer::SystemRenderer(const ScoreArea *scoreArea, const Score &score) : myScoreArea(scoreArea), myScore(score), @@ -228,27 +235,26 @@ void SystemRenderer::drawBarlines(const System &system, int systemIndex, if (barline.hasRehearsalSign() && isFirstStaff) { const RehearsalSign &sign = barline.getRehearsalSign(); - const int y = 1; const int RECTANGLE_OFFSET = 4; auto signLetters = new SimpleTextItem( QString::fromStdString(sign.getLetters()), myRehearsalSignFont); - signLetters->setPos(rehearsalSignX, y); - - auto signText = new QGraphicsSimpleTextItem(); - signText->setPos(rehearsalSignX + - signLetters->boundingRect().width() + 7, y); - signText->setFont(myRehearsalSignFont); + centerSymbolVertically(*signLetters, rehearsalSignX, 0); QFontMetricsF metrics(myRehearsalSignFont); const Barline *nextBar = system.getNextBarline(barline.getPosition()); Q_ASSERT(nextBar); - + const double signTextX = + rehearsalSignX + signLetters->boundingRect().width() + 7; // If the description is too wide, cut it off with an ellipsis. - signText->setText(metrics.elidedText( + QString shortenedSignText = metrics.elidedText( QString::fromStdString(sign.getDescription()), Qt::ElideRight, - layout->getPositionX(nextBar->getPosition()) - signText->x() - - RECTANGLE_OFFSET)); + layout->getPositionX(nextBar->getPosition()) - signTextX - + RECTANGLE_OFFSET); + + auto signText = + new SimpleTextItem(shortenedSignText, myRehearsalSignFont); + centerSymbolVertically(*signText, signTextX, 0); // The tooltip should contain the full description. signText->setToolTip(QString::fromStdString(sign.getDescription())); @@ -257,7 +263,7 @@ void SystemRenderer::drawBarlines(const System &system, int systemIndex, boundingRect.setWidth(boundingRect.width() + 7); boundingRect.translate(-RECTANGLE_OFFSET, 0); auto rect = new QGraphicsRectItem(boundingRect); - rect->setPos(rehearsalSignX, y); + centerSymbolVertically(*rect, rehearsalSignX, 0); rect->setParentItem(myParentSystem); signText->setParentItem(myParentSystem); @@ -503,6 +509,24 @@ static QString getBeatTypeImage(const TempoMarker &tempo) return file; } +static QString getTripletFeelImage(const TempoMarker &tempo) +{ + switch (tempo.getTripletFeel()) + { + case TempoMarker::TripletFeelEighth: + return QStringLiteral(":/images/triplet_feel_eighth.png"); + case TempoMarker::TripletFeelEighthOff: + return QStringLiteral(":/images/triplet_feel_eighth_off.png"); + case TempoMarker::TripletFeelSixteenth: + return QStringLiteral(":/images/triplet_feel_sixteenth.png"); + case TempoMarker::TripletFeelSixteenthOff: + return QStringLiteral(":/images/triplet_feel_sixteenth_off.png"); + default: + Q_ASSERT(false); + return ""; + } +} + void SystemRenderer::drawTempoMarkers(const System &system, const LayoutInfo &layout, double height) @@ -512,7 +536,7 @@ void SystemRenderer::drawTempoMarkers(const System &system, if (tempo.getMarkerType() == TempoMarker::NotShown) continue; - const double location = layout.getPositionX(tempo.getPosition()); + const double x = layout.getPositionX(tempo.getPosition()); auto group = new ClickableGroup([]() { // TODO - allow editing a tempo marker by clicking on it. @@ -538,24 +562,40 @@ void SystemRenderer::drawTempoMarkers(const System &system, const QString imageSpacing(3, ' '); // Add the beat type image. - const int HEIGHT_OFFSET = 2; QFontMetricsF fm(font); QPixmap image(getBeatTypeImage(tempo)); auto pixmap = new QGraphicsPixmapItem(image.scaled( - fm.width(imageSpacing), fm.height() + HEIGHT_OFFSET, + fm.width(imageSpacing), 14, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - pixmap->setPos(fm.width(text), -HEIGHT_OFFSET); + centerSymbolVertically(*pixmap, fm.width(text), height); group->addToGroup(pixmap); text += imageSpacing; text += " = "; text += QString::number(tempo.getBeatsPerMinute()); + + // Add the triplet feel image if necessary. + if (tempo.getTripletFeel() != TempoMarker::NoTripletFeel) + { + text += " ( "; + + const QString imageSpacing(12, ' '); + QPixmap image(getTripletFeelImage(tempo)); + pixmap = new QGraphicsPixmapItem(image.scaled( + fm.width(imageSpacing), 21, + Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + centerSymbolVertically(*pixmap, fm.width(text), height); + group->addToGroup(pixmap); + + text += imageSpacing + " )"; + } } - group->addToGroup(new SimpleTextItem(text, font)); + auto textItem = new SimpleTextItem(text, font); + centerSymbolVertically(*textItem, 0, height); + group->addToGroup(textItem); - const int PADDING = 4; - group->setPos(location, height + PADDING); + group->setX(x); group->setParentItem(myParentSystem); } } @@ -599,7 +639,7 @@ void SystemRenderer::drawChordText(const System &system, auto textItem = new SimpleTextItem(QString::fromStdString(text), myPlainTextFont); - textItem->setPos(x, height + 4); + centerSymbolVertically(*textItem, x, height); textItem->setParentItem(myParentSystem); } } @@ -609,11 +649,11 @@ void SystemRenderer::drawTextItems(const System &system, { for (const TextItem &text : system.getTextItems()) { - const double x = layout.getPositionX(text.getPosition()); const QString &contents = QString::fromStdString(text.getContents()); auto textItem = new SimpleTextItem(contents, myPlainTextFont); - textItem->setPos(x, height + 4); + centerSymbolVertically(*textItem, + layout.getPositionX(text.getPosition()), height); textItem->setParentItem(myParentSystem); } }