comparison view/View.cpp @ 1507:996e971df9e7

Fix, I think, #1914 Mounting rounding error when dragging aligned view left/right - and therefore the associated #1874 Pointer position becomes increasingly erroneous when rewinding with alignment active
author Chris Cannam
date Fri, 13 Sep 2019 17:40:59 +0100
parents 60fe0d20df5d
children 395ef06beab1
comparison
equal deleted inserted replaced
1506:60fe0d20df5d 1507:996e971df9e7
395 // In FramesPerPixel mode, the pixel should be the one "covering" 395 // In FramesPerPixel mode, the pixel should be the one "covering"
396 // the given frame, i.e. to the "left" of it - not necessarily the 396 // the given frame, i.e. to the "left" of it - not necessarily the
397 // nearest boundary. 397 // nearest boundary.
398 398
399 sv_frame_t level = m_zoomLevel.level; 399 sv_frame_t level = m_zoomLevel.level;
400 sv_frame_t fdiff = frame - getCentreFrame(); 400 sv_frame_t fdiff = frame - m_centreFrame;
401 int result = 0; 401 int result = 0;
402 402
403 bool inRange = false; 403 bool inRange = false;
404 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) { 404 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
405 inRange = ((fdiff / level) < sv_frame_t(INT_MAX) && 405 inRange = ((fdiff / level) < sv_frame_t(INT_MAX) &&
412 if (inRange) { 412 if (inRange) {
413 413
414 sv_frame_t adjusted; 414 sv_frame_t adjusted;
415 415
416 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) { 416 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
417 sv_frame_t roundedCentreFrame = (m_centreFrame / level) * level;
418 fdiff = frame - roundedCentreFrame;
417 adjusted = fdiff / level; 419 adjusted = fdiff / level;
418 if ((fdiff < 0) && ((fdiff % level) != 0)) { 420 if ((fdiff < 0) && ((fdiff % level) != 0)) {
419 --adjusted; // round to the left 421 --adjusted; // round to the left
420 } 422 }
421 } else { 423 } else {
440 << "called for locations unadjacent to the current view" 442 << "called for locations unadjacent to the current view"
441 << endl; 443 << endl;
442 return 0; 444 return 0;
443 } 445 }
444 446
447 #ifdef DEBUG_VIEW
448 if (m_zoomLevel.zone == ZoomLevel::PixelsPerFrame) {
449 sv_frame_t reversed = getFrameForX(result);
450 if (reversed != frame) {
451 SVCERR << "View[" << getId() << "]::getXForFrame: WARNING: Converted frame " << frame << " to x " << result << " in PixelsPerFrame zone, but the reverse conversion gives frame " << reversed << " (error = " << reversed - frame << ")" << endl;
452 SVCERR << "(centre frame = " << getCentreFrame() << ", fdiff = "
453 << fdiff << ", level = " << level << ", centre % level = "
454 << (getCentreFrame() % level) << ", fdiff % level = "
455 << (fdiff % level) << ", frame % level = "
456 << (frame % level) << ", reversed % level = "
457 << (reversed % level) << ")" << endl;
458 }
459 }
460 #endif
461
445 return result; 462 return result;
446 } 463 }
447 464
448 sv_frame_t 465 sv_frame_t
449 View::getFrameForX(int x) const 466 View::getFrameForX(int x) const
450 { 467 {
451 // Note, this must always return a value that is on a zoom-level 468 // Note, this must always return a value that is on a zoom-level
452 // boundary - regardless of whether the nominal centre frame is on 469 // boundary - regardless of whether the nominal centre frame is on
453 // such a boundary or not. 470 // such a boundary or not. (It is legitimate for the centre frame
454 471 // not to be on a zoom-level boundary, because the centre frame
455 // In PixelsPerFrame mode, the frame should be the one immediately 472 // may be shared with other views having different zoom levels.)
456 // left of the given pixel, not necessarily the nearest. 473
474 // In FramesPerPixel mode, the frame returned for a given x should
475 // be the first for which getXForFrame(frame) == x; a corollary is
476 // that if the centre frame is not on a zoom-level boundary, then
477 // getFrameForX(x) should not return the centre frame for any x.
478
479 // In PixelsPerFrame mode, the frame returned should be the one
480 // immediately left of the given pixel, not necessarily the
481 // nearest.
457 482
458 int diff = x - (width()/2); 483 int diff = x - (width()/2);
459 sv_frame_t level = m_zoomLevel.level; 484 sv_frame_t level = m_zoomLevel.level;
460 sv_frame_t fdiff, result; 485 sv_frame_t fdiff, result;
461 486
462 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) { 487 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
488 sv_frame_t roundedCentreFrame = (m_centreFrame / level) * level;
463 fdiff = diff * level; 489 fdiff = diff * level;
464 result = ((fdiff + m_centreFrame) / level) * level; 490 result = fdiff + roundedCentreFrame;
465 } else { 491 } else {
466 fdiff = diff / level; 492 fdiff = diff / level;
467 if ((diff < 0) && ((diff % level) != 0)) { 493 if ((diff < 0) && ((diff % level) != 0)) {
468 --fdiff; // round to the left 494 --fdiff; // round to the left
469 } 495 }
470 result = fdiff + m_centreFrame; 496 result = fdiff + m_centreFrame;
471 } 497 }
472 498
473 #ifdef DEBUG_VIEW_WIDGET_PAINT 499 #ifdef DEBUG_VIEW_WIDGET_PAINT
500 /*
474 if (x == 0) { 501 if (x == 0) {
475 SVCERR << "getFrameForX(" << x << "): diff = " << diff << ", fdiff = " 502 SVCERR << "getFrameForX(" << x << "): diff = " << diff << ", fdiff = "
476 << fdiff << ", m_centreFrame = " << m_centreFrame 503 << fdiff << ", m_centreFrame = " << m_centreFrame
477 << ", level = " << m_zoomLevel.level 504 << ", level = " << m_zoomLevel.level
478 << ", diff % level = " << (diff % m_zoomLevel.level) 505 << ", diff % level = " << (diff % m_zoomLevel.level)
479 << ", nominal " << fdiff + m_centreFrame 506 << ", nominal " << fdiff + m_centreFrame
480 << ", will return " << result 507 << ", will return " << result
481 << endl; 508 << endl;
509 }
510 */
511 #endif
512
513 #ifdef DEBUG_VIEW
514 if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
515 int reversed = getXForFrame(result);
516 if (reversed != x) {
517 SVCERR << "View[" << getId() << "]::getFrameForX: WARNING: Converted pixel " << x << " to frame " << result << " in FramesPerPixel zone, but the reverse conversion gives pixel " << reversed << " (error = " << reversed - x << ")" << endl;
518 SVCERR << "(centre frame = " << getCentreFrame()
519 << ", width/2 = " << width()/2 << ", diff = " << diff
520 << ", fdiff = " << fdiff << ", level = " << level
521 << ", centre % level = " << (getCentreFrame() % level)
522 << ", fdiff % level = " << (fdiff % level)
523 << ", frame % level = " << (result % level) << ")" << endl;
524 }
482 } 525 }
483 #endif 526 #endif
484 527
485 return result; 528 return result;
486 } 529 }