comparison view/View.cpp @ 1327:646e713a4632 zoom

Further ZoomLevel fixes
author Chris Cannam
date Thu, 20 Sep 2018 11:45:26 +0100
parents 97c68bffbda6
children 344f29e46258
comparison
equal deleted inserted replaced
1326:97c68bffbda6 1327:646e713a4632
328 { 328 {
329 bool changeVisible = false; 329 bool changeVisible = false;
330 330
331 if (m_centreFrame != f) { 331 if (m_centreFrame != f) {
332 332
333 int formerPixel = int(m_centreFrame / m_zoomLevel); 333 sv_frame_t formerCentre = m_centreFrame;
334
335 m_centreFrame = f; 334 m_centreFrame = f;
336
337 int newPixel = int(m_centreFrame / m_zoomLevel);
338 335
339 if (newPixel != formerPixel) { 336 if (m_zoomLevel.zone == ZoomLevel::PixelsPerFrame) {
340 337
341 #ifdef DEBUG_VIEW_WIDGET_PAINT 338 #ifdef DEBUG_VIEW_WIDGET_PAINT
342 cout << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << endl; 339 SVCERR << "View(" << this << ")::setCentreFrame: in PixelsPerFrame zone, so change must be visible" << endl;
343 #endif 340 #endif
344 update(); 341 update();
345
346 changeVisible = true; 342 changeVisible = true;
343
344 } else {
345
346 int formerPixel = int(formerCentre / m_zoomLevel.level);
347 int newPixel = int(m_centreFrame / m_zoomLevel.level);
348
349 if (newPixel != formerPixel) {
350
351 #ifdef DEBUG_VIEW_WIDGET_PAINT
352 SVCERR << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << endl;
353 #endif
354 update();
355 changeVisible = true;
356 }
347 } 357 }
348 358
349 if (e) { 359 if (e) {
350 sv_frame_t rf = alignToReference(f); 360 sv_frame_t rf = alignToReference(f);
351 #ifdef DEBUG_VIEW 361 #ifdef DEBUG_VIEW
361 } 371 }
362 372
363 int 373 int
364 View::getXForFrame(sv_frame_t frame) const 374 View::getXForFrame(sv_frame_t frame) const
365 { 375 {
366 return int((frame - getStartFrame()) / m_zoomLevel); 376 sv_frame_t fdiff = frame - getCentreFrame();
377
378 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
379 fdiff /= m_zoomLevel.level;
380 } else {
381 fdiff *= m_zoomLevel.level;
382 }
383
384 return int(fdiff + (width()/2));
367 } 385 }
368 386
369 sv_frame_t 387 sv_frame_t
370 View::getFrameForX(int x) const 388 View::getFrameForX(int x) const
371 { 389 {
372 sv_frame_t z = m_zoomLevel; // nb not just int, or multiplication may overflow 390 int diff = x - (width()/2);
373 sv_frame_t frame = m_centreFrame - (width()/2) * z; 391 sv_frame_t fdiff = diff;
374 392
375 frame = (frame / z) * z; // this is start frame 393 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
376 frame = frame + x * z; 394 fdiff *= m_zoomLevel.level;
377 395 } else {
378 #ifdef DEBUG_VIEW_WIDGET_PAINT 396 fdiff /= m_zoomLevel.level;
379 cerr << "View::getFrameForX(" << x << "): z = " << z << ", m_centreFrame = " << m_centreFrame << ", width() = " << width() << ", frame = " << frame << endl; 397 }
380 #endif 398
381 399 return fdiff + m_centreFrame;
382 return frame;
383 } 400 }
384 401
385 double 402 double
386 View::getYForFrequency(double frequency, 403 View::getYForFrequency(double frequency,
387 double minf, 404 double minf,
477 } 494 }
478 495
479 void 496 void
480 View::setZoomLevel(ZoomLevel z) 497 View::setZoomLevel(ZoomLevel z)
481 { 498 {
482 int dpratio = effectiveDevicePixelRatio(); 499 //!!! int dpratio = effectiveDevicePixelRatio();
483 if (z < dpratio) return; 500 // if (z < dpratio) return;
484 if (z < 1) z = 1; 501 // if (z < 1) z = 1;
485 if (m_zoomLevel != int(z)) { 502 if (m_zoomLevel == z) {
486 m_zoomLevel = z; 503 return;
487 emit zoomLevelChanged(z, m_followZoom); 504 }
488 update(); 505 m_zoomLevel = z;
489 } 506 emit zoomLevelChanged(z, m_followZoom);
507 update();
490 } 508 }
491 509
492 bool 510 bool
493 View::hasLightBackground() const 511 View::hasLightBackground() const
494 { 512 {
1398 } 1416 }
1399 1417
1400 return nonScrollables; 1418 return nonScrollables;
1401 } 1419 }
1402 1420
1403 int 1421 ZoomLevel
1404 View::getZoomConstraintBlockSize(int blockSize, 1422 View::getZoomConstraintLevel(ZoomLevel zoomLevel,
1405 ZoomConstraint::RoundingDirection dir) 1423 ZoomConstraint::RoundingDirection dir)
1406 const 1424 const
1407 { 1425 {
1408 int candidate = blockSize; 1426 using namespace std::rel_ops;
1427
1428 ZoomLevel candidate = zoomLevel;
1409 bool haveCandidate = false; 1429 bool haveCandidate = false;
1410 1430
1411 PowerOfSqrtTwoZoomConstraint defaultZoomConstraint; 1431 PowerOfSqrtTwoZoomConstraint defaultZoomConstraint;
1412 1432
1413 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) { 1433 for (auto i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
1414 1434
1415 const ZoomConstraint *zoomConstraint = (*i)->getZoomConstraint(); 1435 const ZoomConstraint *zoomConstraint = (*i)->getZoomConstraint();
1416 if (!zoomConstraint) zoomConstraint = &defaultZoomConstraint; 1436 if (!zoomConstraint) zoomConstraint = &defaultZoomConstraint;
1417 1437
1418 int thisBlockSize = 1438 ZoomLevel thisLevel =
1419 zoomConstraint->getNearestBlockSize(blockSize, dir); 1439 zoomConstraint->getNearestZoomLevel(zoomLevel, dir);
1420 1440
1421 // Go for the block size that's furthest from the one 1441 // Go for the block size that's furthest from the one
1422 // passed in. Most of the time, that's what we want. 1442 // passed in. Most of the time, that's what we want.
1423 if (!haveCandidate || 1443 if (!haveCandidate ||
1424 (thisBlockSize > blockSize && thisBlockSize > candidate) || 1444 (thisLevel > zoomLevel && thisLevel > candidate) ||
1425 (thisBlockSize < blockSize && thisBlockSize < candidate)) { 1445 (thisLevel < zoomLevel && thisLevel < candidate)) {
1426 candidate = thisBlockSize; 1446 candidate = thisLevel;
1427 haveCandidate = true; 1447 haveCandidate = true;
1428 } 1448 }
1429 } 1449 }
1430 1450
1431 return candidate; 1451 return candidate;
1462 } else { 1482 } else {
1463 newZoomLevel = getZoomConstraintLevel(m_zoomLevel.incremented(), 1483 newZoomLevel = getZoomConstraintLevel(m_zoomLevel.incremented(),
1464 ZoomConstraint::RoundUp); 1484 ZoomConstraint::RoundUp);
1465 } 1485 }
1466 1486
1487 using namespace std::rel_ops;
1488
1467 if (newZoomLevel != m_zoomLevel) { 1489 if (newZoomLevel != m_zoomLevel) {
1468 setZoomLevel(newZoomLevel); 1490 setZoomLevel(newZoomLevel);
1469 } 1491 }
1470 } 1492 }
1471 1493
1761 #ifdef DEBUG_VIEW_WIDGET_PAINT 1783 #ifdef DEBUG_VIEW_WIDGET_PAINT
1762 cerr << "View(" << this << "): cache " << m_cache << ", cache zoom " 1784 cerr << "View(" << this << "): cache " << m_cache << ", cache zoom "
1763 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl; 1785 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl;
1764 #endif 1786 #endif
1765 1787
1788 using namespace std::rel_ops;
1789
1766 if (!m_cache || 1790 if (!m_cache ||
1767 m_cacheZoomLevel != m_zoomLevel || 1791 m_cacheZoomLevel != m_zoomLevel ||
1768 scaledCacheSize != m_cache->size()) { 1792 scaledCacheSize != m_cache->size()) {
1769 1793
1770 // cache is not valid 1794 // cache is not valid
2366 } 2390 }
2367 2391
2368 bool 2392 bool
2369 View::render(QPainter &paint, int xorigin, sv_frame_t f0, sv_frame_t f1) 2393 View::render(QPainter &paint, int xorigin, sv_frame_t f0, sv_frame_t f1)
2370 { 2394 {
2371 int x0 = int(f0 / m_zoomLevel); 2395 int x0 = int(round(m_zoomLevel.framesToPixels(double(f0))));
2372 int x1 = int(f1 / m_zoomLevel); 2396 int x1 = int(round(m_zoomLevel.framesToPixels(double(f1))));
2373 2397
2374 int w = x1 - x0; 2398 int w = x1 - x0;
2375 2399
2376 sv_frame_t origCentreFrame = m_centreFrame; 2400 sv_frame_t origCentreFrame = m_centreFrame;
2377 2401
2429 m_centreFrame = origCentreFrame; 2453 m_centreFrame = origCentreFrame;
2430 update(); 2454 update();
2431 return false; 2455 return false;
2432 } 2456 }
2433 2457
2434 m_centreFrame = f0 + (x + width()/2) * m_zoomLevel; 2458 m_centreFrame = f0 + sv_frame_t(round(m_zoomLevel.pixelsToFrames
2459 (x + width()/2)));
2435 2460
2436 QRect chunk(0, 0, width(), height()); 2461 QRect chunk(0, 0, width(), height());
2437 2462
2438 paint.setPen(getBackground()); 2463 paint.setPen(getBackground());
2439 paint.setBrush(getBackground()); 2464 paint.setBrush(getBackground());
2480 } 2505 }
2481 2506
2482 QImage * 2507 QImage *
2483 View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1) 2508 View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1)
2484 { 2509 {
2485 int x0 = int(f0 / getZoomLevel()); 2510 int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
2486 int x1 = int(f1 / getZoomLevel()); 2511 int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
2487 2512
2488 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32); 2513 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32);
2489 2514
2490 QPainter *paint = new QPainter(image); 2515 QPainter *paint = new QPainter(image);
2491 if (!render(*paint, 0, f0, f1)) { 2516 if (!render(*paint, 0, f0, f1)) {
2508 } 2533 }
2509 2534
2510 QSize 2535 QSize
2511 View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1) 2536 View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1)
2512 { 2537 {
2513 int x0 = int(f0 / getZoomLevel()); 2538 int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
2514 int x1 = int(f1 / getZoomLevel()); 2539 int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
2515 2540
2516 return QSize(x1 - x0, height()); 2541 return QSize(x1 - x0, height());
2517 } 2542 }
2518 2543
2519 bool 2544 bool
2526 } 2551 }
2527 2552
2528 bool 2553 bool
2529 View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1) 2554 View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1)
2530 { 2555 {
2531 int x0 = int(f0 / getZoomLevel()); 2556 int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
2532 int x1 = int(f1 / getZoomLevel()); 2557 int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
2533 2558
2534 QSvgGenerator generator; 2559 QSvgGenerator generator;
2535 generator.setFileName(filename); 2560 generator.setFileName(filename);
2536 generator.setSize(QSize(x1 - x0, height())); 2561 generator.setSize(QSize(x1 - x0, height()));
2537 generator.setViewBox(QRect(0, 0, x1 - x0, height())); 2562 generator.setViewBox(QRect(0, 0, x1 - x0, height()));
2549 View::toXml(QTextStream &stream, 2574 View::toXml(QTextStream &stream,
2550 QString indent, QString extraAttributes) const 2575 QString indent, QString extraAttributes) const
2551 { 2576 {
2552 stream << indent; 2577 stream << indent;
2553 2578
2579 int classicZoomValue, deepZoomValue;
2580
2581 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
2582 classicZoomValue = m_zoomLevel.level;
2583 deepZoomValue = 1;
2584 } else {
2585 classicZoomValue = 1;
2586 deepZoomValue = m_zoomLevel.level;
2587 }
2588
2554 stream << QString("<view " 2589 stream << QString("<view "
2555 "centre=\"%1\" " 2590 "centre=\"%1\" "
2556 "zoom=\"%2\" " 2591 "zoom=\"%2\" "
2557 "followPan=\"%3\" " 2592 "deepZoom=\"%3\" "
2558 "followZoom=\"%4\" " 2593 "followPan=\"%4\" "
2559 "tracking=\"%5\" " 2594 "followZoom=\"%5\" "
2595 "tracking=\"%6\" "
2560 " %6>\n") 2596 " %6>\n")
2561 .arg(m_centreFrame) 2597 .arg(m_centreFrame)
2562 .arg(m_zoomLevel) 2598 .arg(classicZoomValue)
2599 .arg(deepZoomValue)
2563 .arg(m_followPan) 2600 .arg(m_followPan)
2564 .arg(m_followZoom) 2601 .arg(m_followZoom)
2565 .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" : 2602 .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" :
2566 m_followPlay == PlaybackScrollPageWithCentre ? "page" : 2603 m_followPlay == PlaybackScrollPageWithCentre ? "page" :
2567 m_followPlay == PlaybackScrollPage ? "daw" : 2604 m_followPlay == PlaybackScrollPage ? "daw" :