1 //=============================================================================
2 //  MusE Reader
3 //  Music Score Reader
4 //
5 //  Copyright (C) 2010 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 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19 
20 #include "mscore/globals.h"
21 #include "omrview.h"
22 #include "omr.h"
23 #include "libmscore/page.h"
24 #include "omrpage.h"
25 #include "libmscore/score.h"
26 #include "mscore/scoreview.h"
27 #include "libmscore/sym.h"
28 #include "libmscore/mscore.h"
29 
30 namespace Ms {
31 
32 //---------------------------------------------------------
33 //   OmrView
34 //---------------------------------------------------------
35 
OmrView(ScoreView * sv,QWidget * parent)36 OmrView::OmrView(ScoreView* sv, QWidget* parent)
37    : QWidget(parent)
38       {
39       setFocusPolicy(Qt::StrongFocus);
40       setAttribute(Qt::WA_InputMethodEnabled);
41       setAttribute(Qt::WA_KeyCompression);
42       setMouseTracking(true);
43 
44       _omr       = 0;
45       _scoreView = sv;
46       double m   = .25;
47       _fotoMode  = false;
48       _matrix    = QTransform(m, 0.0, 0.0, m, 0.0, 0.0);
49       xoff = yoff = 0;
50       _showLines      = false;
51       _showBarlines   = true;
52       _showSlices     = true;
53       _showStaves     = true;
54       }
55 
56 //---------------------------------------------------------
57 //   setOmr
58 //---------------------------------------------------------
59 
setOmr(Omr * s)60 void OmrView::setOmr(Omr* s)
61       {
62       delete _omr;
63       _omr    = s;
64       if (s == 0 || s->numPages() == 0) {
65             maxTiles = 0;
66             return;
67             }
68       int n                = s->numPages();
69       OmrPage* page        = _omr->page(0);
70       const QImage& i      = page->image();
71       Score* score         = _scoreView->score();
72       double mag           = _omr->spatium() / score->spatium();
73       pageWidth            = lrint(score->styleD(Sid::pageWidth) * mag * DPI);
74 
75       int htiles = ((pageWidth + TILE_W - 1) / TILE_W);
76       pageWidth  = htiles * TILE_W;
77       int vtiles = (i.height() + TILE_H - 1) / TILE_H;
78       maxTiles   = n * htiles *  vtiles;
79       }
80 
81 //---------------------------------------------------------
82 //   initTile
83 //---------------------------------------------------------
84 
initTile(Tile * t)85 void OmrView::initTile(Tile* t)
86       {
87       int page1  = t->r.x() / pageWidth;
88       if (page1 < 0)
89             page1 = 0;
90       int n = _omr->numPages();
91       if (page1 >= n)
92             return;
93 
94       t->page     = _omr->page(page1);
95       t->pageNo   = page1;
96 
97       const QImage& i = t->page->image();
98       int xoffset     = 0; // (pageWidth - i.width()) / 2;
99       int x           = t->r.x() - (t->pageNo * pageWidth) - xoffset;
100       t->pm           = QPixmap::fromImage(i.copy(x, t->r.y(), TILE_W, TILE_H));
101       }
102 
103 //---------------------------------------------------------
104 //   Tile
105 //---------------------------------------------------------
106 
Tile()107 Tile::Tile()
108    : no(0), r(0, 0, TILE_W, TILE_H), pm(TILE_W, TILE_H)
109       {
110       }
111 
112 //---------------------------------------------------------
113 //   paintEvent
114 //---------------------------------------------------------
115 
paintEvent(QPaintEvent * event)116 void OmrView::paintEvent(QPaintEvent* event)
117       {
118       if (_omr == 0)
119             return;
120 
121       QPainter p(this);
122       p.setTransform(_matrix);
123 
124       QRect r(event->rect());
125 
126       //
127       // remove unused tiles
128       //
129       QRect rr = _matrix.inverted().mapRect(QRectF(r)).toRect();
130       rr.adjust(-1, -1, 2, 2);
131 
132       QList<Tile*> nl;
133       for(Tile* t : usedTiles) {
134             if (t->r.intersects(rr))
135                   nl.append(t);
136             else
137                   freeTiles.append(t);
138             }
139 #if QT_VERSION >= 0x040800
140       usedTiles.swap(nl);
141 #else
142       QList<Tile*> tmp = nl;
143       nl = usedTiles;
144       usedTiles = tmp;
145 #endif
146 
147       //
148       // add visible tiles
149       //
150       Score* score    = _scoreView->score();
151 
152       double sSpatium = score->spatium();
153       double spatium  = _omr->spatium();
154       double mag      = spatium / sSpatium;
155 
156       int w = pageWidth;
157       int h = lrint(score->styleD(Sid::pageHeight) * mag * DPI);
158       int n = _omr->numPages();
159 
160       int nx = (w * n) / TILE_W;
161       int ny = (h + TILE_H - 1) / TILE_H;
162 
163       int y1 = rr.y() / TILE_H;
164       int y2 = (rr.y() + rr.height() + TILE_H - 1) / TILE_H;
165       int x1 = rr.x() / TILE_W;
166       int x2 = (rr.x() + rr.width() + TILE_W -1) / TILE_W;
167 
168       if (x1 < 0)
169             x1 = 0;
170       if (y1 < 0)
171             y1 = 0;
172       if (x2 > nx)
173             x2 = nx;
174       if (y2 > ny)
175             y2 = ny;
176 
177       for (int y = y1; y < y2; ++y) {
178             for (int x = x1; x < x2; ++x) {
179                   int no = nx * y + x;
180                   if (no < 0 || no >= maxTiles)
181                         continue;
182                   int i;
183                   for (i = 0; i < usedTiles.size(); ++i) {
184                         if (usedTiles[i]->no == no)
185                               break;
186                         }
187                   if (i == usedTiles.size()) {
188                         // create new tile
189                         Tile* t = freeTiles.isEmpty() ? new Tile : freeTiles.pop();
190                         t->no = no;
191                         t->r  = QRect(x * TILE_W, y * TILE_H, TILE_W, TILE_H);
192                         initTile(t);
193                         usedTiles.append(t);
194                         }
195                   }
196             }
197 
198       int minPage = 9000;
199       int maxPage = 0;
200       for(const Tile* t : usedTiles) {
201             p.drawPixmap(t->r, t->pm);
202             if (t->pageNo < minPage)
203                   minPage = t->pageNo;
204             if (t->pageNo > maxPage)
205                   maxPage = t->pageNo;
206             }
207       for (int pageNo = minPage; pageNo <= maxPage; ++pageNo) {
208             OmrPage* page = _omr->page(pageNo);
209             p.save();
210             p.translate(w * pageNo, 0);
211             if (_showLines) {
212                   p.setPen(QPen(QColor(255, 0, 0, 80), 1.0));
213                   for(QLine l : page->sl())
214                         p.drawLine(QLineF(l.x1()+.5, l.y1()+.5, l.x2()+.5, l.y2()+.5));
215                   }
216             if (_showSlices) {
217                   for(const QRect r1 : page->slices())
218                         p.fillRect(r1, QBrush(QColor(0, 100, 100, 50)));
219                   }
220 
221             if (_showStaves) {
222                   for(const OmrSystem& s : page->systems()) {       // staves
223                         for(const OmrStaff& r1 : s.staves())
224                               p.fillRect(r1, QBrush(QColor(0, 0, 100, 50)));
225                         }
226                   }
227 
228             for (const OmrSystem& system : page->systems()) {
229                   if (_showBarlines) {
230                         p.setPen(QPen(Qt::blue, 3.0));
231                         for(const QLineF& l : system.barLines)
232                             for(int w1 = 0; w1 < 10; w1++)
233                               p.drawLine(l.x1()+w1, l.y1(), l.x2()+w1, l.y2() ); //add width to barline
234                         }
235 
236                   for (const OmrStaff& staff : system.staves()) {
237                         for (const OmrNote* n1 : staff.notes()) {
238                             if (n1->sym == SymId::noteheadBlack)
239                                     p.setPen(QPen(QColor(255, 0, 0), 2.0));
240                               else
241                                     p.setPen(QPen(QColor(0, 0, 255), 2.0));
242                               p.drawRect(*n1);
243                               }
244                         }
245                   }
246             p.restore();
247             }
248 
249       if (fotoMode()) {
250             // TODO
251             p.setBrush(QColor(0, 0, 50, 50));
252             QPen pen(QColor(0, 0, 255));
253             // always 2 pixel width
254             qreal w1 = 2.0 / p.matrix().m11();
255             pen.setWidthF(w1);
256             p.setPen(pen);
257             p.drawRect(_foto);
258             }
259       }
260 
261 //---------------------------------------------------------
262 //   mousePressEvent
263 //---------------------------------------------------------
264 
mousePressEvent(QMouseEvent * e)265 void OmrView::mousePressEvent(QMouseEvent* e)
266       {
267       startDrag = e->pos();
268       }
269 
270 //---------------------------------------------------------
271 //   mouseMoveEvent
272 //---------------------------------------------------------
273 
mouseMoveEvent(QMouseEvent * e)274 void OmrView::mouseMoveEvent(QMouseEvent* e)
275       {
276       if (QApplication::mouseButtons()) {
277             QPoint delta = e->pos() - startDrag;
278             int dx       = delta.x();
279             int dy       = delta.y();
280             xoff += dx;
281             yoff += dy;
282             _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
283                _matrix.m22(), _matrix.m23(), _matrix.dx()+dx, _matrix.dy()+dy, _matrix.m33());
284 
285             scroll(dx, dy, QRect(0, 0, width(), height()));
286             startDrag = e->pos();
287             }
288       }
289 
290 //---------------------------------------------------------
291 //   setMag
292 //---------------------------------------------------------
293 
setMag(double nmag)294 void OmrView::setMag(double nmag)
295       {
296       qreal m = mag();
297 
298       if (nmag == m)
299             return;
300       double deltamag = nmag / m;
301 
302       _matrix.setMatrix(nmag, _matrix.m12(), _matrix.m13(), _matrix.m21(),
303          nmag, _matrix.m23(), _matrix.dx()*deltamag, _matrix.dy()*deltamag, _matrix.m33());
304       }
305 
306 //---------------------------------------------------------
307 //   zoom
308 //---------------------------------------------------------
309 
zoom(int step,const QPoint & pos)310 void OmrView::zoom(int step, const QPoint& pos)
311       {
312       QTransform imatrix(_matrix.inverted());
313       QPointF p1 = imatrix.map(QPointF(pos));
314       double _scale = mag();
315       if (step > 0) {
316             for (int i = 0; i < step; ++i)
317                    _scale *= 1.1;
318             }
319       else {
320             for (int i = 0; i < -step; ++i)
321                   _scale /= 1.1;
322             }
323       if (_scale > 16.0)
324             _scale = 16.0;
325       else if (_scale < 0.05)
326             _scale = 0.05;
327       setMag(_scale);
328 
329       QPointF p2 = imatrix.map(QPointF(pos));
330       QPointF p3 = p2 - p1;
331       int dx     = lrint(p3.x() * _scale);
332       int dy     = lrint(p3.y() * _scale);
333 
334       _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
335          _matrix.m22(), _matrix.m23(), _matrix.dx()+dx, _matrix.dy()+dy, _matrix.m33());
336       scroll(dx, dy, QRect(0, 0, width(), height()));
337       update();
338       }
339 
340 //---------------------------------------------------------
341 //   wheelEvent
342 //---------------------------------------------------------
343 
wheelEvent(QWheelEvent * event)344 void OmrView::wheelEvent(QWheelEvent* event)
345       {
346       if (event->modifiers() & Qt::ControlModifier) {
347             QApplication::sendPostedEvents(this, 0);
348             zoom(event->delta() / 120, event->pos());
349             return;
350             }
351       int dx = 0;
352       int dy = 0;
353       if (event->modifiers() & Qt::ShiftModifier || event->orientation() == Qt::Horizontal) {
354             //
355             //    scroll horizontal
356             //
357             int n = width() / 10;
358             if (n < 2)
359                   n = 2;
360             dx = event->delta() * n / 120;
361             }
362       else {
363             //
364             //    scroll vertical
365             //
366             int n = height() / 10;
367             if (n < 2)
368                   n = 2;
369             dy = event->delta() * n / 120;
370             }
371 
372       _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
373          _matrix.m22(), _matrix.m23(), _matrix.dx()+dx, _matrix.dy()+dy, _matrix.m33());
374       scroll(dx, dy, QRect(0, 0, width(), height()));
375       }
376 
377 //---------------------------------------------------------
378 //   setScale
379 //---------------------------------------------------------
380 
setScale(double v)381 void OmrView::setScale(double v)
382       {
383       double spatium = _omr->spatium();
384       setMag(v/spatium);
385       update();
386       }
387 
388 //---------------------------------------------------------
389 //   setOffset
390 //---------------------------------------------------------
391 
setOffset(double x,double y)392 void OmrView::setOffset(double x, double y)
393       {
394       Score* score    = _omr->score();
395       double sSpatium = score->spatium() * _scoreView->matrix().m11();
396       double spatium  = _omr->spatium() * _matrix.m11();
397 
398       double nx = x / sSpatium * spatium + xoff;
399       double ny = y / sSpatium * spatium + yoff;
400 
401       double ox = _matrix.dx();
402       double oy = _matrix.dy();
403 
404       _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
405          _matrix.m22(), _matrix.m23(), nx, ny, _matrix.m33());
406 
407       scroll(ox-nx, oy-ny, QRect(0, 0, width(), height()));
408       update();
409       }
410 
411 //---------------------------------------------------------
412 //   contextMenuEvent
413 //---------------------------------------------------------
414 
contextMenuEvent(QContextMenuEvent *)415 void OmrView::contextMenuEvent(QContextMenuEvent*)
416       {
417 //printf("context menu\n");
418       }
419 
420 //---------------------------------------------------------
421 //   setShowBarlines
422 //---------------------------------------------------------
423 
setShowBarlines(bool val)424 void OmrView::setShowBarlines(bool val)
425       {
426       _showBarlines = val;
427       update();
428       }
429 
430 //---------------------------------------------------------
431 //   setShowSlices
432 //---------------------------------------------------------
433 
setShowSlices(bool val)434 void OmrView::setShowSlices(bool val)
435       {
436       _showSlices = val;
437       update();
438       }
439 
440 //---------------------------------------------------------
441 //   setShowStaves
442 //---------------------------------------------------------
443 
setShowStaves(bool val)444 void OmrView::setShowStaves(bool val)
445       {
446       _showStaves = val;
447       update();
448       }
449 
450 }
451 
452 
453