1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "vibrato.h"
14 #include "style.h"
15 #include "system.h"
16 #include "measure.h"
17 #include "xml.h"
18 #include "utils.h"
19 #include "sym.h"
20 #include "score.h"
21 #include "accidental.h"
22 #include "segment.h"
23 #include "staff.h"
24
25 namespace Ms {
26
27 //---------------------------------------------------------
28 // vibratoTable
29 // must be in sync with Vibrato::Type
30 //---------------------------------------------------------
31
32 const VibratoTableItem vibratoTable[] = {
33 { Vibrato::Type::GUITAR_VIBRATO, "guitarVibrato", QT_TRANSLATE_NOOP("vibratoType", "Guitar vibrato") },
34 { Vibrato::Type::GUITAR_VIBRATO_WIDE, "guitarVibratoWide", QT_TRANSLATE_NOOP("vibratoType", "Guitar vibrato wide") },
35 { Vibrato::Type::VIBRATO_SAWTOOTH, "vibratoSawtooth", QT_TRANSLATE_NOOP("vibratoType", "Vibrato sawtooth") },
36 { Vibrato::Type::VIBRATO_SAWTOOTH_WIDE, "vibratoSawtoothWide", QT_TRANSLATE_NOOP("vibratoType", "Tremolo sawtooth wide") }
37 };
38
vibratoTableSize()39 int vibratoTableSize() {
40 return sizeof(vibratoTable)/sizeof(VibratoTableItem);
41 }
42
43 //---------------------------------------------------------
44 // draw
45 //---------------------------------------------------------
46
draw(QPainter * painter) const47 void VibratoSegment::draw(QPainter* painter) const
48 {
49 painter->setPen(spanner()->curColor());
50 drawSymbols(_symbols, painter);
51 }
52
53 //---------------------------------------------------------
54 // symbolLine
55 //---------------------------------------------------------
56
symbolLine(SymId start,SymId fill)57 void VibratoSegment::symbolLine(SymId start, SymId fill)
58 {
59 qreal x1 = 0;
60 qreal x2 = pos2().x();
61 qreal w = x2 - x1;
62 qreal mag = magS();
63 ScoreFont* f = score()->scoreFont();
64
65 _symbols.clear();
66 _symbols.push_back(start);
67 qreal w1 = f->advance(start, mag);
68 qreal w2 = f->advance(fill, mag);
69 int n = lrint((w - w1) / w2);
70 for (int i = 0; i < n; ++i)
71 _symbols.push_back(fill);
72 QRectF r(f->bbox(_symbols, mag));
73 setbbox(r);
74 }
75
symbolLine(SymId start,SymId fill,SymId end)76 void VibratoSegment::symbolLine(SymId start, SymId fill, SymId end)
77 {
78 qreal x1 = 0;
79 qreal x2 = pos2().x();
80 qreal w = x2 - x1;
81 qreal mag = magS();
82 ScoreFont* f = score()->scoreFont();
83
84 _symbols.clear();
85 _symbols.push_back(start);
86 qreal w1 = f->bbox(start, mag).width();
87 qreal w2 = f->width(fill, mag);
88 qreal w3 = f->width(end, mag);
89 int n = lrint((w - w1 - w3) / w2);
90 for (int i = 0; i < n; ++i)
91 _symbols.push_back(fill);
92 _symbols.push_back(end);
93 QRectF r(f->bbox(_symbols, mag));
94 setbbox(r);
95 }
96
97 //---------------------------------------------------------
98 // layout
99 //---------------------------------------------------------
100
layout()101 void VibratoSegment::layout()
102 {
103 if (staff())
104 setMag(staff()->mag(tick()));
105 if (spanner()->placeBelow())
106 rypos() = staff() ? staff()->height() : 0.0;
107
108 if (isSingleType() || isBeginType()) {
109 switch (vibrato()->vibratoType()) {
110 case Vibrato::Type::GUITAR_VIBRATO:
111 symbolLine(SymId::guitarVibratoStroke, SymId::guitarVibratoStroke);
112 break;
113 case Vibrato::Type::GUITAR_VIBRATO_WIDE:
114 symbolLine(SymId::guitarWideVibratoStroke, SymId::guitarWideVibratoStroke);
115 break;
116 case Vibrato::Type::VIBRATO_SAWTOOTH:
117 symbolLine(SymId::wiggleSawtooth, SymId::wiggleSawtooth);
118 break;
119 case Vibrato::Type::VIBRATO_SAWTOOTH_WIDE:
120 symbolLine(SymId::wiggleSawtoothWide, SymId::wiggleSawtoothWide);
121 break;
122 }
123 }
124 else
125 symbolLine(SymId::wiggleVibrato, SymId::wiggleVibrato);
126 if (isStyled(Pid::OFFSET))
127 roffset() = vibrato()->propertyDefault(Pid::OFFSET).toPointF();
128
129 autoplaceSpannerSegment();
130 }
131
132 //---------------------------------------------------------
133 // shape
134 //---------------------------------------------------------
135
shape() const136 Shape VibratoSegment::shape() const
137 {
138 return Shape(bbox());
139 }
140
141 //---------------------------------------------------------
142 // propertyDelegate
143 //---------------------------------------------------------
144
propertyDelegate(Pid pid)145 Element* VibratoSegment::propertyDelegate(Pid pid)
146 {
147 if (pid == Pid::VIBRATO_TYPE || pid == Pid::PLACEMENT || pid == Pid::PLAY)
148 return spanner();
149 return LineSegment::propertyDelegate(pid);
150 }
151
152 //---------------------------------------------------------
153 // vibratoStyle
154 //---------------------------------------------------------
155
156 static const ElementStyle vibratoStyle {
157 { Sid::vibratoPlacement, Pid::PLACEMENT },
158 { Sid::vibratoPosAbove, Pid::OFFSET },
159 };
160
161 //---------------------------------------------------------
162 // Vibrato
163 //---------------------------------------------------------
164
Vibrato(Score * s)165 Vibrato::Vibrato(Score* s)
166 : SLine(s)
167 {
168 initElementStyle(&vibratoStyle);
169 _vibratoType = Type::GUITAR_VIBRATO;
170 setPlayArticulation(true);
171 }
172
~Vibrato()173 Vibrato::~Vibrato()
174 {
175 }
176
177 //---------------------------------------------------------
178 // layout
179 //---------------------------------------------------------
180
layout()181 void Vibrato::layout()
182 {
183 SLine::layout();
184 if (score() == gscore)
185 return;
186 if (spannerSegments().empty()) {
187 qDebug("Vibrato: no segments");
188 return;
189 }
190 }
191
192 static const ElementStyle vibratoSegmentStyle {
193 { Sid::vibratoPosAbove, Pid::OFFSET },
194 { Sid::vibratoMinDistance, Pid::MIN_DISTANCE },
195 };
196
197 //---------------------------------------------------------
198 // createLineSegment
199 //---------------------------------------------------------
200
createLineSegment()201 LineSegment* Vibrato::createLineSegment()
202 {
203 VibratoSegment* seg = new VibratoSegment(this, score());
204 seg->setTrack(track());
205 seg->setColor(color());
206 seg->initElementStyle(&vibratoSegmentStyle);
207 return seg;
208 }
209
210 //---------------------------------------------------------
211 // Vibrato::write
212 //---------------------------------------------------------
213
write(XmlWriter & xml) const214 void Vibrato::write(XmlWriter& xml) const
215 {
216 if (!xml.canWrite(this))
217 return;
218 xml.stag(this);
219 xml.tag("subtype", vibratoTypeName());
220 writeProperty(xml, Pid::PLAY);
221 for (const StyledProperty& spp : *styledProperties())
222 writeProperty(xml, spp.pid);
223 SLine::writeProperties(xml);
224 xml.etag();
225 }
226
227 //---------------------------------------------------------
228 // Vibrato::read
229 //---------------------------------------------------------
230
read(XmlReader & e)231 void Vibrato::read(XmlReader& e)
232 {
233 eraseSpannerSegments();
234
235 while (e.readNextStartElement()) {
236 const QStringRef& tag(e.name());
237 if (tag == "subtype")
238 setVibratoType(e.readElementText());
239 else if ( tag == "play")
240 setPlayArticulation(e.readBool());
241 else if (!SLine::readProperties(e))
242 e.unknown();
243 }
244 }
245
246 //---------------------------------------------------------
247 // setVibratoType
248 //---------------------------------------------------------
249
setVibratoType(const QString & s)250 void Vibrato::setVibratoType(const QString& s)
251 {
252 for (VibratoTableItem i : vibratoTable) {
253 if (s.compare(i.name) == 0) {
254 _vibratoType = i.type;
255 return;
256 }
257 }
258 qDebug("Vibrato::setSubtype: unknown <%s>", qPrintable(s));
259 }
260
261 //---------------------------------------------------------
262 // type2name
263 //---------------------------------------------------------
264
type2name(Vibrato::Type t)265 QString Vibrato::type2name(Vibrato::Type t)
266 {
267 for (VibratoTableItem i : vibratoTable) {
268 if (i.type == t)
269 return i.name;
270 }
271 qDebug("unknown Vibrato subtype %d", int(t));
272 return "?";
273 }
274
275 //---------------------------------------------------------
276 // vibratoTypeName
277 //---------------------------------------------------------
278
vibratoTypeName() const279 QString Vibrato::vibratoTypeName() const
280 {
281 return type2name(vibratoType());
282 }
283
284 //---------------------------------------------------------
285 // vibratoTypeName
286 //---------------------------------------------------------
287
vibratoTypeUserName() const288 QString Vibrato::vibratoTypeUserName() const
289 {
290 return qApp->translate("vibratoType", vibratoTable[static_cast<int>(vibratoType())].userName.toUtf8().constData());
291 }
292
293 //---------------------------------------------------------
294 // getPropertyStyle
295 //---------------------------------------------------------
296
getPropertyStyle(Pid pid) const297 Sid VibratoSegment::getPropertyStyle(Pid pid) const
298 {
299 if (pid == Pid::OFFSET)
300 return spanner()->placeAbove() ? Sid::vibratoPosAbove : Sid::vibratoPosBelow;
301 return LineSegment::getPropertyStyle(pid);
302 }
303
getPropertyStyle(Pid pid) const304 Sid Vibrato::getPropertyStyle(Pid pid) const
305 {
306 if (pid == Pid::OFFSET)
307 return placeAbove() ? Sid::vibratoPosAbove : Sid::vibratoPosBelow;
308 return SLine::getPropertyStyle(pid);
309 }
310
311 //---------------------------------------------------------
312 // getProperty
313 //---------------------------------------------------------
314
getProperty(Pid propertyId) const315 QVariant Vibrato::getProperty(Pid propertyId) const
316 {
317 switch(propertyId) {
318 case Pid::VIBRATO_TYPE:
319 return int(vibratoType());
320 case Pid::PLAY:
321 return bool(playArticulation());
322 default:
323 break;
324 }
325 return SLine::getProperty(propertyId);
326 }
327
328 //---------------------------------------------------------
329 // setProperty
330 //---------------------------------------------------------
331
setProperty(Pid propertyId,const QVariant & val)332 bool Vibrato::setProperty(Pid propertyId, const QVariant& val)
333 {
334 switch(propertyId) {
335 case Pid::VIBRATO_TYPE:
336 setVibratoType(Type(val.toInt()));
337 break;
338 case Pid::PLAY:
339 setPlayArticulation(val.toBool());
340 break;
341 default:
342 if (!SLine::setProperty(propertyId, val))
343 return false;
344 break;
345 }
346 triggerLayoutAll();
347 return true;
348 }
349
350 //---------------------------------------------------------
351 // propertyDefault
352 //---------------------------------------------------------
353
propertyDefault(Pid propertyId) const354 QVariant Vibrato::propertyDefault(Pid propertyId) const
355 {
356 switch(propertyId) {
357 case Pid::VIBRATO_TYPE:
358 return 0;
359 case Pid::PLAY:
360 return true;
361 case Pid::PLACEMENT:
362 return score()->styleV(Sid::vibratoPlacement);
363 default:
364 return SLine::propertyDefault(propertyId);
365 }
366 }
367
368 //---------------------------------------------------------
369 // propertyId
370 //---------------------------------------------------------
371
propertyId(const QStringRef & name) const372 Pid Vibrato::propertyId(const QStringRef& name) const
373 {
374 if (name == "subtype")
375 return Pid::VIBRATO_TYPE;
376 return SLine::propertyId(name);
377 }
378
379 //---------------------------------------------------------
380 // undoSetVibratoType
381 //---------------------------------------------------------
382
undoSetVibratoType(Type val)383 void Vibrato::undoSetVibratoType(Type val)
384 {
385 undoChangeProperty(Pid::VIBRATO_TYPE, int(val));
386 }
387
388 //---------------------------------------------------------
389 // accessibleInfo
390 //---------------------------------------------------------
391
accessibleInfo() const392 QString Vibrato::accessibleInfo() const
393 {
394 return QString("%1: %2").arg(Element::accessibleInfo(), vibratoTypeUserName());
395 }
396 }
397
398