Mercurial > hg > svgui
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" : |