Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "imageviewer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Tnz6 includes
Toshihiro Shimizu 890ddd
#include "tapp.h"
Toshihiro Shimizu 890ddd
#include "menubarcommandids.h"
Toshihiro Shimizu 890ddd
#include "flipbook.h"
Toshihiro Shimizu 890ddd
#include "histogrampopup.h"
Shinya Kitaoka 120a6e
#include "sceneviewer.h"  // ToggleCommandHandler
Shinya Kitaoka 120a6e
#include "mainwindow.h"   //RecentFiles
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolcommandids.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tools/cursormanager.h"
Toshihiro Shimizu 890ddd
#include "tools/stylepicker.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/menubarcommand.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/viewcommandids.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
shun-iwasawa ad7711
#include "toonzqt/lutcalibrator.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/tscenehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/sceneproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/palettecontroller.h"
Toshihiro Shimizu 890ddd
#include "toonz/tpalettehandle.h"
shun-iwasawa 388550
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qmenu></qmenu>
Toshihiro Shimizu 890ddd
#include <qaction></qaction>
Toshihiro Shimizu 890ddd
#include <qmouseevent></qmouseevent>
Toshihiro Shimizu 890ddd
#include <qwheelevent></qwheelevent>
shun-iwasawa ad7711
#include <qopenglframebufferobject></qopenglframebufferobject>
manongjohn 2c447c
#include <qgestureevent></qgestureevent>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern ToggleCommandHandler safeAreaToggle;
Toshihiro Shimizu 890ddd
extern void getSafeAreaData(double &_smallSize, double &_largeSize);
Toshihiro Shimizu 890ddd
// enable to choose safe area from a list, and enable to draw multiple lines
Toshihiro Shimizu 890ddd
extern void getSafeAreaSizeList(QList<qlist<double>> &_sizeList);</qlist<double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
// enable to choose safe area from a list, and enable to draw multiple lines
Shinya Kitaoka 120a6e
void drawSafeArea(const TRectD box) {
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  glLoadIdentity();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tglColor(TPixel32::Red);
Shinya Kitaoka 120a6e
  glLineStipple(1, 0xCCCC);
Shinya Kitaoka 120a6e
  glEnable(GL_LINE_STIPPLE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tglDrawRect(box);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QList<qlist<double>> sizeList;</qlist<double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  getSafeAreaSizeList(sizeList);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = 0; i < sizeList.size(); i++) {
Shinya Kitaoka 120a6e
    QList<double> curSize = sizeList.at(i);</double>
Shinya Kitaoka 120a6e
    if (curSize.size() == 5)
Shinya Kitaoka 120a6e
      tglColor(
Shinya Kitaoka 120a6e
          TPixel((int)curSize.at(2), (int)curSize.at(3), (int)curSize.at(4)));
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      tglColor(TPixel32::Red);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double facX = -0.5 * (1 - curSize.at(0) / 100.0);
Shinya Kitaoka 120a6e
    double facY = -0.5 * (1 - curSize.at(1) / 100.0);
Shinya Kitaoka 120a6e
    tglDrawRect(box.enlarge(facX * box.getLx(), facY * box.getLy()));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDisable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect getImageBounds(const TImageP &img) {
Shinya Kitaoka 120a6e
  if (TRasterImageP ri = img)
Shinya Kitaoka 120a6e
    return ri->getRaster()->getBounds();
Shinya Kitaoka 120a6e
  else if (TToonzImageP ti = img)
Shinya Kitaoka 120a6e
    return ti->getRaster()->getBounds();
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TVectorImageP vi = img;
Shinya Kitaoka 120a6e
    return convert(vi->getBBox());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRectD getImageBoundsD(const TImageP &img) {
Shinya Kitaoka 120a6e
  if (TRasterImageP ri = img)
Shinya Kitaoka 120a6e
    return TRectD(0, 0, ri->getRaster()->getLx(), ri->getRaster()->getLy());
Shinya Kitaoka 120a6e
  else if (TToonzImageP ti = img)
Shinya Kitaoka 120a6e
    return TRectD(0, 0, ti->getSize().lx, ti->getSize().ly);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TVectorImageP vi = img;
Shinya Kitaoka 120a6e
    return vi->getBBox();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class FlipZoomer final : public ImageUtils::ShortcutZoomer {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FlipZoomer(ImageViewer *parent) : ShortcutZoomer(parent) {}
Shinya Kitaoka 120a6e
shun-iwasawa 92d40c
  bool zoom(bool zoomin, bool resetView) override {
shun-iwasawa 92d40c
    static_cast<imageviewer *="">(getWidget())->zoomQt(zoomin, resetView);</imageviewer>
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool fit() override {
Shinya Kitaoka 120a6e
    static_cast<imageviewer *="">(getWidget())->fitView();</imageviewer>
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 92d40c
  bool resetZoom() override {
shun-iwasawa 92d40c
    static_cast<imageviewer *="">(getWidget())->resetZoom();</imageviewer>
shun-iwasawa 92d40c
    return true;
shun-iwasawa 92d40c
  }
shun-iwasawa 92d40c
Shinya Kitaoka 473e70
  bool toggleFullScreen(bool quit) override {
Shinya Kitaoka 120a6e
    if (ImageUtils::FullScreenWidget *fsWidget =
Shinya Kitaoka 120a6e
            dynamic_cast<imageutils::fullscreenwidget *="">(</imageutils::fullscreenwidget>
Shinya Kitaoka 120a6e
                getWidget()->parentWidget()))
Shinya Kitaoka 120a6e
      return fsWidget->toggleFullScreen(quit);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ImageViewerShortcutReceiver {
Shinya Kitaoka 120a6e
  FlipBook *m_flipbook;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ImageViewerShortcutReceiver(FlipBook *flipbook) : m_flipbook(flipbook) {}
Shinya Kitaoka 120a6e
  ~ImageViewerShortcutReceiver() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool exec(QKeyEvent *event) {
Shinya Kitaoka 120a6e
    CommandManager *cManager = CommandManager::instance();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (event->key() == cManager->getKeyFromId(MI_FreezePreview)) {
Shinya Kitaoka 120a6e
      m_flipbook->isFreezed() ? m_flipbook->unfreezePreview()
Shinya Kitaoka 120a6e
                              : m_flipbook->freezePreview();
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (event->key() == cManager->getKeyFromId(MI_ClonePreview)) {
Shinya Kitaoka 120a6e
      m_flipbook->clonePreview();
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (event->key() == cManager->getKeyFromId(MI_RegeneratePreview)) {
Shinya Kitaoka 120a6e
      m_flipbook->regenerate();
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (event->key() == cManager->getKeyFromId(MI_RegenerateFramePr)) {
Shinya Kitaoka 120a6e
      m_flipbook->regenerateFrame();
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================
Toshihiro Shimizu 890ddd
//    ImageViewer class
Toshihiro Shimizu 890ddd
//--------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \class ImageViewer
Shinya Kitaoka 120a6e
                \brief The ImageViewer class provides to view an image.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
                Inherits \b QOpenGLWidget.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
                The object allows also to manage pan and zoom event. It's
Shinya Kitaoka 120a6e
   possible to set a
Shinya Kitaoka 120a6e
                color mask TRop::ColorMask to image view.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
/*! \fn void ImageViewer::setColorMask(UCHAR colorMask)
Shinya Kitaoka 120a6e
                Set current TRop::ColorMask color mask to \b colorMask.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
/*! \fn TImageP ImageViewer::getImage()
Shinya Kitaoka 120a6e
                Return current image viewer.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
/*! \fn TAffine ImageViewer::getViewAff()
luz paz 6454c4
                Return current viewer matrix transformation.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ImageViewer::ImageViewer(QWidget *parent, FlipBook *flipbook,
Shinya Kitaoka 120a6e
                         bool showHistogram)
shun_iwasawa 7c988d
    : GLWidgetForHighDpi(parent)
Shinya Kitaoka 120a6e
    , m_pressedMousePos(0, 0)
Shinya Kitaoka 120a6e
    , m_mouseButton(Qt::NoButton)
Shinya Kitaoka 120a6e
    , m_draggingZoomSelection(false)
Shinya Kitaoka 120a6e
    , m_image()
shun-iwasawa 481b59
    , m_orgImage()
Shinya Kitaoka 120a6e
    , m_FPS(0)
Shinya Kitaoka 120a6e
    , m_viewAff()
Shinya Kitaoka 120a6e
    , m_pos(0, 0)
Shinya Kitaoka 120a6e
    , m_visualSettings()
Shinya Kitaoka 120a6e
    , m_compareSettings()
Shinya Kitaoka 120a6e
    , m_isHistogramEnable(showHistogram)
Shinya Kitaoka 120a6e
    , m_flipbook(flipbook)
Shinya Kitaoka 120a6e
    , m_isColorModel(false)
Shinya Kitaoka 120a6e
    , m_histogramPopup(0)
Shinya Kitaoka 120a6e
    , m_isRemakingPreviewFx(false)
manongjohn 2c447c
    , m_rectRGBPick(false)
shun-iwasawa fe0983
    , m_firstImage(true)
shun-iwasawa fe0983
    , m_timer(nullptr) {
Shinya Kitaoka 120a6e
  m_visualSettings.m_sceneProperties =
Shinya Kitaoka 120a6e
      TApp::instance()->getCurrentScene()->getScene()->getProperties();
Shinya Kitaoka 120a6e
  m_visualSettings.m_drawExternalBG = true;
Shinya Kitaoka 120a6e
  setAttribute(Qt::WA_KeyCompression);
Shinya Kitaoka 120a6e
  setFocusPolicy(Qt::StrongFocus);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  setMouseTracking(true);
Shinya Kitaoka 120a6e
manongjohn 2c447c
  setAttribute(Qt::WA_AcceptTouchEvents);
manongjohn 2c447c
  grabGesture(Qt::SwipeGesture);
manongjohn 2c447c
  grabGesture(Qt::PanGesture);
manongjohn 2c447c
  grabGesture(Qt::PinchGesture);
manongjohn 2c447c
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable)
Shinya Kitaoka 120a6e
    m_histogramPopup = new HistogramPopup(tr("Flipbook Histogram"));
shun-iwasawa 388550
shun-iwasawa 388550
  if (Preferences::instance()->isColorCalibrationEnabled())
shun-iwasawa 388550
    m_lutCalibrator = new LutCalibrator();
shun-iwasawa 215a5b
shun-iwasawa 215a5b
  if (Preferences::instance()->is30bitDisplayEnabled())
shun-iwasawa 215a5b
    setTextureFormat(TGL_TexFmt10);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::contextMenuEvent(QContextMenuEvent *event) {
Shinya Kitaoka 120a6e
  QAction *action;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_isColorModel) {
Shinya Kitaoka 120a6e
    event->ignore();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QMenu *menu = new QMenu(this);
Shinya Kitaoka 120a6e
manongjohn 2c447c
  if (m_flipbook) {
manongjohn 2c447c
    if (m_flipbook->getPreviewedFx()) {
manongjohn 2c447c
      if (!(windowState() & Qt::WindowFullScreen)) {
manongjohn 2c447c
        action = menu->addAction(tr("Clone Preview"));
manongjohn 2c447c
        action->setShortcut(QKeySequence(
manongjohn 2c447c
            CommandManager::instance()->getKeyFromId(MI_ClonePreview)));
manongjohn 2c447c
        connect(action, SIGNAL(triggered()), m_flipbook, SLOT(clonePreview()));
manongjohn 2c447c
      }
Shinya Kitaoka 120a6e
manongjohn 2c447c
      if (m_flipbook->isFreezed()) {
manongjohn 2c447c
        action = menu->addAction(tr("Unfreeze Preview"));
manongjohn 2c447c
        action->setShortcut(QKeySequence(
manongjohn 2c447c
            CommandManager::instance()->getKeyFromId(MI_FreezePreview)));
manongjohn 2c447c
        connect(action, SIGNAL(triggered()), m_flipbook,
manongjohn 2c447c
                SLOT(unfreezePreview()));
manongjohn 2c447c
      } else {
manongjohn 2c447c
        action = menu->addAction(tr("Freeze Preview"));
manongjohn 2c447c
        action->setShortcut(QKeySequence(
manongjohn 2c447c
            CommandManager::instance()->getKeyFromId(MI_FreezePreview)));
manongjohn 2c447c
        connect(action, SIGNAL(triggered()), m_flipbook, SLOT(freezePreview()));
manongjohn 2c447c
      }
manongjohn 2c447c
manongjohn 2c447c
      action = menu->addAction(tr("Regenerate Preview"));
Shinya Kitaoka 120a6e
      action->setShortcut(QKeySequence(
manongjohn 2c447c
          CommandManager::instance()->getKeyFromId(MI_RegeneratePreview)));
manongjohn 2c447c
      connect(action, SIGNAL(triggered()), m_flipbook, SLOT(regenerate()));
manongjohn 2c447c
manongjohn 2c447c
      action = menu->addAction(tr("Regenerate Frame Preview"));
Shinya Kitaoka 120a6e
      action->setShortcut(QKeySequence(
manongjohn 2c447c
          CommandManager::instance()->getKeyFromId(MI_RegenerateFramePr)));
manongjohn 2c447c
      connect(action, SIGNAL(triggered()), m_flipbook, SLOT(regenerateFrame()));
manongjohn 2c447c
manongjohn 2c447c
      menu->addSeparator();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
manongjohn 2c447c
    action = menu->addAction(tr("Load / Append Images"));
manongjohn 2c447c
    connect(action, SIGNAL(triggered()), m_flipbook, SLOT(loadImages()));
Shinya Kitaoka 120a6e
manongjohn 2c447c
    // history of the loaded paths of flipbook
manongjohn 2c447c
    action = CommandManager::instance()->getAction(MI_LoadRecentImage);
manongjohn 2c447c
    menu->addAction(action);
manongjohn 2c447c
    action->setParent(m_flipbook);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    menu->addSeparator();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QAction *reset = menu->addAction(tr("Reset View"));
Shinya Kitaoka 120a6e
  reset->setShortcut(
manongjohn 4f0f61
      QKeySequence(CommandManager::instance()->getKeyFromId(V_ViewReset)));
Shinya Kitaoka 120a6e
  connect(reset, SIGNAL(triggered()), SLOT(resetView()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QAction *fit = menu->addAction(tr("Fit To Window"));
Shinya Kitaoka 120a6e
  fit->setShortcut(
Shinya Kitaoka 120a6e
      QKeySequence(CommandManager::instance()->getKeyFromId(V_ZoomFit)));
Shinya Kitaoka 120a6e
  connect(fit, SIGNAL(triggered()), SLOT(fitView()));
Toshihiro Shimizu 890ddd
manongjohn 2c447c
  if (m_flipbook) {
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
manongjohn 2c447c
    if (ImageUtils::FullScreenWidget *fsWidget =
manongjohn 2c447c
            dynamic_cast<imageutils::fullscreenwidget *="">(parentWidget())) {</imageutils::fullscreenwidget>
manongjohn 2c447c
      bool isFullScreen = (fsWidget->windowState() & Qt::WindowFullScreen) != 0;
Toshihiro Shimizu 890ddd
manongjohn 2c447c
      action = menu->addAction(isFullScreen ? tr("Exit Full Screen Mode")
manongjohn 2c447c
                                            : tr("Full Screen Mode"));
Toshihiro Shimizu 890ddd
manongjohn 2c447c
      action->setShortcut(QKeySequence(
manongjohn 2c447c
          CommandManager::instance()->getKeyFromId(V_ShowHideFullScreen)));
manongjohn 2c447c
      connect(action, SIGNAL(triggered()), fsWidget, SLOT(toggleFullScreen()));
manongjohn 2c447c
    }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
manongjohn 2c447c
    bool addedSep = false;
Toshihiro Shimizu 890ddd
manongjohn 2c447c
    if (m_isHistogramEnable &&
manongjohn 2c447c
        visibleRegion().contains(event->pos() * getDevPixRatio())) {
manongjohn 2c447c
      menu->addSeparator();
manongjohn 2c447c
      addedSep = true;
manongjohn 2c447c
      action   = menu->addAction(tr("Show Histogram"));
manongjohn 2c447c
      connect(action, SIGNAL(triggered()), SLOT(showHistogram()));
manongjohn 2c447c
    }
Toshihiro Shimizu 890ddd
manongjohn 2c447c
    if (m_visualSettings.m_doCompare) {
shun-iwasawa cea18b
      if (!addedSep) {
shun-iwasawa cea18b
        menu->addSeparator();
shun-iwasawa cea18b
        addedSep = true;
shun-iwasawa cea18b
      }
manongjohn 2c447c
      action = menu->addAction(tr("Swap Compared Images"));
manongjohn 2c447c
      connect(action, SIGNAL(triggered()), SLOT(swapCompared()));
manongjohn 2c447c
    }
shun-iwasawa cea18b
shun-iwasawa cea18b
    if (m_flipbook->isSavable()) {
shun-iwasawa cea18b
      if (!addedSep) menu->addSeparator();
shun-iwasawa cea18b
      action = menu->addAction(tr("Save Images"));
shun-iwasawa cea18b
      connect(action, SIGNAL(triggered()), m_flipbook, SLOT(saveImages()));
shun-iwasawa cea18b
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  menu->exec(event->globalPos());
Toshihiro Shimizu 890ddd
manongjohn 2c447c
  if (m_flipbook) {
manongjohn 2c447c
    action = CommandManager::instance()->getAction(MI_LoadRecentImage);
manongjohn 2c447c
    action->setParent(0);
manongjohn 2c447c
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  delete menu;
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::setVisual(const ImagePainter::VisualSettings &settings) {
shun-iwasawa d5045c
  if (m_isHistogramEnable && m_histogramPopup &&
shun-iwasawa d5045c
      settings.m_doCompare != m_visualSettings.m_doCompare) {
shun-iwasawa d5045c
    m_histogramPopup->setShowCompare(settings.m_doCompare);
shun-iwasawa d5045c
  }
Shinya Kitaoka 120a6e
  m_visualSettings = settings;
Shinya Kitaoka 120a6e
  m_visualSettings.m_sceneProperties =
Shinya Kitaoka 120a6e
      TApp::instance()->getCurrentScene()->getScene()->getProperties();
Shinya Kitaoka 120a6e
  m_visualSettings.m_drawExternalBG = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Keisuke Ogaki 0c8292
Shinya Kitaoka 120a6e
ImageViewer::~ImageViewer() {
Shinya Kitaoka 120a6e
  // iwsw commented out temporarily
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
  if (m_ghibli3DLutUtil)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
          m_ghibli3DLutUtil->onEnd();
Shinya Kitaoka 120a6e
          delete m_ghibli3DLutUtil;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  */
shun-iwasawa ad7711
  if (m_fbo) delete m_fbo;
Keisuke Ogaki 0c8292
}
Keisuke Ogaki 0c8292
Keisuke Ogaki 0c8292
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*! Set current image to \b image and update. If Histogram is visible set its
Shinya Kitaoka 120a6e
 * image.
shun-iwasawa b766d1
 */
shun-iwasawa 481b59
void ImageViewer::setImage(TImageP image, TImageP orgImage) {
shun-iwasawa 481b59
  m_image    = image;
shun-iwasawa 481b59
  m_orgImage = orgImage;
Shinya Kitaoka 120a6e
manongjohn 2c447c
  if (m_image && m_firstImage) {
manongjohn 2c447c
    m_firstImage = false;
manongjohn 2c447c
    fitView();
shun-iwasawa b766d1
    // when the viewer size is large enough, limit the zoom ratio to 100% so
shun-iwasawa b766d1
    // that the image is shown in actual pixel size without jaggies due to
shun-iwasawa b766d1
    // resampling.
shun-iwasawa b766d1
    if (fabs(m_viewAff.det()) > 1.0) resetView();
manongjohn 2c447c
  }
manongjohn 2c447c
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable && m_histogramPopup->isVisible())
shun-iwasawa 481b59
    m_histogramPopup->setImage((orgImage) ? orgImage : image);
shun-iwasawa fe0983
shun-iwasawa fe0983
  // make sure to redraw the frame here.
shun-iwasawa fe0983
  // repaint() does NOT immediately redraw the frame for QOpenGLWidget
shun-iwasawa fe0983
  update();
shun-iwasawa 56a0d5
  if (!isColorModel()) qApp->processEvents();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::setHistogramTitle(QString levelName) {
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable && m_histogramPopup->isVisible()) {
Shinya Kitaoka 120a6e
    QString histogramTitle = QString("Histogram  ::  ") + levelName;
Shinya Kitaoka 120a6e
    m_histogramPopup->setTitle(histogramTitle);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::setHistogramEnable(bool enable) {
Shinya Kitaoka 120a6e
  m_isHistogramEnable = enable;
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable && !m_histogramPopup)
Shinya Kitaoka 120a6e
    m_histogramPopup = new HistogramPopup(tr("Flipbook Histogram"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::hideHistogram() {
Shinya Kitaoka 120a6e
  if (!m_isHistogramEnable) return;
Shinya Kitaoka 120a6e
  m_histogramPopup->setImage(TImageP());
Shinya Kitaoka 120a6e
  if (m_histogramPopup->isVisible()) {
Shinya Kitaoka 120a6e
    m_histogramPopup->hide();
Shinya Kitaoka 120a6e
    m_histogramPopup->setTitle(tr("Flipbook Histogram"));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::initializeGL() {
shun_iwasawa 5e0d4f
  initializeOpenGLFunctions();
shun-iwasawa ad7711
shun-iwasawa ad7711
  // to be computed once through the software
shun-iwasawa e40777
  if (m_lutCalibrator && !m_lutCalibrator->isInitialized()) {
shun-iwasawa 388550
    m_lutCalibrator->initialize();
shun-iwasawa 388550
    connect(context(), SIGNAL(aboutToBeDestroyed()), this,
shun-iwasawa 388550
            SLOT(onContextAboutToBeDestroyed()));
shun-iwasawa 388550
  }
shun-iwasawa ad7711
Shinya Kitaoka 120a6e
  // glClearColor(1.0,1.0,1.0,1);
Shinya Kitaoka 120a6e
  glClear(GL_COLOR_BUFFER_BIT);
shun-iwasawa e40777
shun-iwasawa e40777
  if (m_firstInitialized)
shun-iwasawa e40777
    m_firstInitialized = false;
shun-iwasawa e40777
  else {
shun-iwasawa e40777
    resizeGL(width(), height());
shun-iwasawa e40777
    update();
shun-iwasawa e40777
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::resizeGL(int w, int h) {
shun_iwasawa 1c961d
  w *= getDevPixRatio();
shun_iwasawa 1c961d
  h *= getDevPixRatio();
Shinya Kitaoka 120a6e
  glViewport(0, 0, w, h);
Shinya Kitaoka 120a6e
  glMatrixMode(GL_PROJECTION);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  double nearPlane   = 100;
Shinya Kitaoka 120a6e
  double farPlane    = 2500;
Shinya Kitaoka 120a6e
  double centerPlane = 1100;
Shinya Kitaoka 120a6e
  glOrtho(0, w, 0, h, -4000, 4000);
Shinya Kitaoka 120a6e
  glMatrixMode(GL_MODELVIEW);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  glTranslatef(0.375, 0.375, 0.0);
Shinya Kitaoka 120a6e
  glTranslated(w * 0.5, h * 0.5, 0);
Shinya Kitaoka 120a6e
shun-iwasawa ad7711
  // remake fbo with new size
shun-iwasawa 388550
  if (m_lutCalibrator && m_lutCalibrator->isValid()) {
shun-iwasawa ad7711
    if (m_fbo) delete m_fbo;
shun-iwasawa 215a5b
    if (Preferences::instance()->is30bitDisplayEnabled()) {
shun-iwasawa 215a5b
      QOpenGLFramebufferObjectFormat format;
shun-iwasawa 215a5b
      format.setInternalTextureFormat(TGL_TexFmt10);
shun-iwasawa 215a5b
      m_fbo = new QOpenGLFramebufferObject(w, h, format);
shun-iwasawa 215a5b
    } else  // normally, initialize with GL_RGBA8 format
shun-iwasawa 215a5b
      m_fbo = new QOpenGLFramebufferObject(w, h);
shun-iwasawa ad7711
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::paintGL() {
shun-iwasawa 215a5b
  initializeOpenGLFunctions();
shun-iwasawa 388550
  if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->bind();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimension viewerSize(width(), height());
Shinya Kitaoka 120a6e
  TAffine aff = m_viewAff;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if (!m_visualSettings.m_defineLoadbox && m_flipbook &&
Shinya Kitaoka 120a6e
  // m_flipbook->getLoadbox()!=TRect())
Shinya Kitaoka 120a6e
  //  offs =
Shinya Kitaoka 120a6e
  //  convert(m_flipbook->getLoadbox().getP00())-TPointD(m_flipbook->getImageSize().lx/2.0,
Shinya Kitaoka 120a6e
  //  m_flipbook->getImageSize().ly/2.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimension imageSize;
Shinya Kitaoka 120a6e
  TRect loadbox;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_flipbook) {
Shinya Kitaoka 120a6e
    QString title =
Shinya Kitaoka 120a6e
        (!m_image)
Shinya Kitaoka 120a6e
            ? m_flipbook->getTitle() + tr("  ::  Zoom : ") +
Shinya Kitaoka 120a6e
                  QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %"
Shinya Kitaoka 120a6e
            : m_flipbook->getLevelZoomTitle() + tr("  ::  Zoom : ") +
Shinya Kitaoka 120a6e
                  QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %";
Shinya Kitaoka 120a6e
    m_flipbook->parentWidget()->setWindowTitle(title);
Shinya Kitaoka 120a6e
    imageSize = m_flipbook->getImageSize();
Shinya Kitaoka 120a6e
    if (m_visualSettings.m_useLoadbox && m_flipbook->getLoadbox() != TRect())
Shinya Kitaoka 120a6e
      loadbox = m_flipbook->getLoadbox();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_visualSettings.m_sceneProperties =
Shinya Kitaoka 120a6e
      TApp::instance()->getCurrentScene()->getScene()->getProperties();
Shinya Kitaoka 120a6e
  // enable checks only in the color model
Shinya Kitaoka 120a6e
  m_visualSettings.m_useChecks = m_isColorModel;
Shinya Kitaoka 120a6e
  ImagePainter::paintImage(m_image, imageSize, viewerSize, aff,
Shinya Kitaoka 120a6e
                           m_visualSettings, m_compareSettings, loadbox);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // when fx parameter is modified with showing the fx preview,
Shinya Kitaoka 120a6e
  // a flipbook shows a red border line before the rendered result is shown.
Shinya Kitaoka 120a6e
  if (m_isRemakingPreviewFx) {
Shinya Kitaoka 120a6e
    glPushMatrix();
Shinya Kitaoka 120a6e
    glLoadIdentity();
Shinya Kitaoka 120a6e
    glColor3d(1.0, 0.0, 0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_LOOP);
Shinya Kitaoka 120a6e
    glVertex2d(5, 5);
Shinya Kitaoka 120a6e
    glVertex2d(5, height() - 5);
Shinya Kitaoka 120a6e
    glVertex2d(width() - 5, height() - 5);
Shinya Kitaoka 120a6e
    glVertex2d(width() - 5, 5);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_LOOP);
Shinya Kitaoka 120a6e
    glVertex2d(10, 10);
Shinya Kitaoka 120a6e
    glVertex2d(10, height() - 10);
Shinya Kitaoka 120a6e
    glVertex2d(width() - 10, height() - 10);
Shinya Kitaoka 120a6e
    glVertex2d(width() - 10, 10);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
    glPopMatrix();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_image) {
shun-iwasawa 388550
    if (m_lutCalibrator && m_lutCalibrator->isValid())
shun-iwasawa 388550
      m_lutCalibrator->onEndDraw(m_fbo);
shun-iwasawa fe0983
    if (m_timer && m_timer->isValid()) {
shun-iwasawa fe0983
      qint64 currentInstant = m_timer->nsecsElapsed();
shun-iwasawa fe0983
      while (currentInstant < m_targetInstant) {
shun-iwasawa fe0983
        currentInstant = m_timer->nsecsElapsed();
shun-iwasawa fe0983
      }
shun-iwasawa fe0983
    }
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (safeAreaToggle.getStatus() && !m_isColorModel) {
Shinya Kitaoka 120a6e
    TRasterImageP rimg = (TRasterImageP)m_image;
Shinya Kitaoka 120a6e
    TVectorImageP vimg = (TVectorImageP)m_image;
Shinya Kitaoka 120a6e
    TToonzImageP timg  = (TToonzImageP)m_image;
Shinya Kitaoka 120a6e
    TRect bbox;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD centerD;
Shinya Kitaoka 120a6e
    TRect bounds;
Shinya Kitaoka 120a6e
    if (rimg) {
Shinya Kitaoka 120a6e
      centerD = rimg->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
      bounds  = rimg->getRaster()->getBounds();
Shinya Kitaoka 120a6e
    } else if (timg) {
Shinya Kitaoka 120a6e
      centerD = timg->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
      bounds  = timg->getRaster()->getBounds();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!vimg) {
Shinya Kitaoka 120a6e
      TAffine aff = TTranslation(viewerSize.lx * 0.5, viewerSize.ly * 0.5) *
Shinya Kitaoka 120a6e
                    m_viewAff * TTranslation(-centerD);
Shinya Kitaoka 120a6e
      TRectD bbox = aff * TRectD(0, 0, bounds.getLx() - 1, bounds.getLy() - 1);
Shinya Kitaoka 120a6e
      drawSafeArea(bbox);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TPoint fromPos, toPos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_visualSettings.m_defineLoadbox && m_flipbook) {
Shinya Kitaoka 120a6e
    TRect loadbox =
Shinya Kitaoka 120a6e
        convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox()));
Shinya Kitaoka 120a6e
    if (loadbox != TRect()) {
Shinya Kitaoka 120a6e
      TPoint p00 = loadbox.getP00();
Shinya Kitaoka 120a6e
      TPoint p11 = loadbox.getP11();
Shinya Kitaoka 120a6e
      fromPos =
Shinya Kitaoka 120a6e
          TPoint(p00.x - width() * 0.5,
Shinya Kitaoka 120a6e
                 height() * 0.5 - p00.y);  // m_flipbook->getLoadbox().getP00();
Shinya Kitaoka 120a6e
      toPos =
Shinya Kitaoka 120a6e
          TPoint(p11.x - width() * 0.5,
Shinya Kitaoka 120a6e
                 height() * 0.5 - p11.y);  // m_flipbook->getLoadbox().getP11();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (m_draggingZoomSelection || m_rectRGBPick) {
Shinya Kitaoka 120a6e
    fromPos = TPoint(m_pressedMousePos.x - width() * 0.5,
Shinya Kitaoka 120a6e
                     height() * 0.5 - m_pressedMousePos.y);
shun-iwasawa b766d1
    toPos   = TPoint(m_pos.x() - width() * 0.5, height() * 0.5 - m_pos.y());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (fromPos != TPoint() || toPos != TPoint()) {
Shinya Kitaoka 120a6e
    if (m_rectRGBPick) {
Shinya Kitaoka 120a6e
      tglColor(TPixel32::Red);
Shinya Kitaoka 120a6e
      // TODO: glLineStipple is deprecated in the latest OpenGL. Need to be
Shinya Kitaoka 120a6e
      // replaced. (shun_iwasawa 2015/12/25)
Shinya Kitaoka 120a6e
      glLineStipple(1, 0x3F33);
Shinya Kitaoka 120a6e
      glEnable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
      // do not draw the rect around the mouse cursor
Shinya Kitaoka 120a6e
      int margin = (fromPos.y < toPos.y) ? -3 : 3;
Shinya Kitaoka 120a6e
      glVertex2i(toPos.x, toPos.y + margin);
Shinya Kitaoka 120a6e
      glVertex2i(toPos.x, fromPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(fromPos.x, fromPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(fromPos.x, toPos.y);
Shinya Kitaoka 120a6e
      margin = (fromPos.x < toPos.x) ? -3 : 3;
Shinya Kitaoka 120a6e
      glVertex2i(toPos.x + margin, toPos.y);
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
      glDisable(GL_LINE_STIPPLE);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglColor(m_draggingZoomSelection ? TPixel32::Red : TPixel32::Blue);
Shinya Kitaoka 120a6e
      glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
      glVertex2i(fromPos.x, fromPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(fromPos.x, toPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(toPos.x, toPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(toPos.x, fromPos.y);
Shinya Kitaoka 120a6e
      glVertex2i(fromPos.x, fromPos.y);
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 388550
  if (m_lutCalibrator && m_lutCalibrator->isValid())
shun-iwasawa 388550
    m_lutCalibrator->onEndDraw(m_fbo);
shun-iwasawa fe0983
shun-iwasawa fe0983
  // wait to achieve precise fps
shun-iwasawa fe0983
  if (m_timer && m_timer->isValid()) {
shun-iwasawa fe0983
    qint64 currentInstant = m_timer->nsecsElapsed();
shun-iwasawa fe0983
    while (currentInstant < m_targetInstant) {
shun-iwasawa fe0983
      currentInstant = m_timer->nsecsElapsed();
shun-iwasawa fe0983
    }
shun-iwasawa fe0983
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
luz paz 67b4e9
/*! Add to current transformation matrix a \b delta translation.
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::panQt(const QPoint &delta) {
Shinya Kitaoka 120a6e
  if (delta == QPoint()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // stop panning when the image is at the edge of window
Shinya Kitaoka 120a6e
  QPoint delta_(delta.x(), delta.y());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TToonzImageP timg  = (TToonzImageP)m_image;
Shinya Kitaoka 120a6e
  TRasterImageP rimg = (TRasterImageP)m_image;
Shinya Kitaoka 120a6e
  if (timg || rimg) {
Shinya Kitaoka 120a6e
    bool isXPlus = delta.x() > 0;
Shinya Kitaoka 120a6e
    bool isYPlus = delta.y() > 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TDimension imgSize((timg) ? timg->getSize() : rimg->getRaster()->getSize());
Shinya Kitaoka 120a6e
    int subSampling = (timg) ? timg->getSubsampling() : rimg->getSubsampling();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TPointD cornerPos = TPointD(imgSize.lx * ((isXPlus) ? -1 : 1),
Shinya Kitaoka 120a6e
                                imgSize.ly * ((isYPlus) ? 1 : -1)) *
Shinya Kitaoka 120a6e
                        (0.5 / (double)subSampling);
Shinya Kitaoka 120a6e
    cornerPos = m_viewAff * cornerPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((cornerPos.x > 0) == isXPlus) delta_.setX(0);
Shinya Kitaoka 120a6e
    if ((cornerPos.y < 0) == isYPlus) delta_.setY(0);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setViewAff(TTranslation(delta_.x(), -delta_.y()) * m_viewAff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
luz paz 67b4e9
/*! Add to current transformation matrix a \b center translation matched with a
Shinya Kitaoka 120a6e
                scale of factor \b factor. Apply a zoom of factor \b factor with
Shinya Kitaoka 120a6e
   center
Shinya Kitaoka 120a6e
                \b center.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void ImageViewer::zoomQt(const QPoint ¢er, double factor) {
Shinya Kitaoka 120a6e
  if (factor == 1.0) return;
Shinya Kitaoka 120a6e
  TPointD delta(center.x(), center.y());
shun-iwasawa 7a435f
  double scale2 = fabs(m_viewAff.det());
shun-iwasawa 7a435f
  if ((scale2 < 100000 || factor < 1) && (scale2 > 0.001 * 0.05 || factor > 1))
shun-iwasawa 7a435f
    setViewAff(TTranslation(delta) * TScale(factor) * TTranslation(-delta) *
shun-iwasawa 7a435f
               m_viewAff);
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::zoomQt(bool forward, bool reset) {
Shinya Kitaoka 120a6e
  double scale2 = m_viewAff.det();
Shinya Kitaoka 120a6e
  if (reset)
Shinya Kitaoka 120a6e
    setViewAff(TAffine());
Shinya Kitaoka 120a6e
  else if (((scale2 < 100000 || !forward) &&
Shinya Kitaoka 120a6e
            (scale2 > 0.001 * 0.05 || forward))) {
Shinya Kitaoka 120a6e
    double oldZoomScale = sqrt(scale2);
Shinya Kitaoka 120a6e
    double zoomScale =
Shinya Kitaoka 120a6e
        reset ? 1 : ImageUtils::getQuantizedZoomFactor(oldZoomScale, forward);
Shinya Kitaoka 120a6e
    setViewAff(TScale(zoomScale / oldZoomScale) * m_viewAff);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 92d40c
void ImageViewer::resetZoom() {
shun-iwasawa 92d40c
  double oldZoomScale = sqrt(m_viewAff.det());
shun-iwasawa 92d40c
  setViewAff(TScale(1.0 / oldZoomScale) * m_viewAff);
shun-iwasawa 92d40c
  update();
shun-iwasawa 92d40c
}
shun-iwasawa 92d40c
shun-iwasawa 92d40c
//-----------------------------------------------------------------------------
shun-iwasawa 92d40c
Shinya Kitaoka 120a6e
void ImageViewer::dragCompare(const QPoint &dp) {
Shinya Kitaoka 120a6e
  if (m_compareSettings.m_dragCompareX)
Shinya Kitaoka 120a6e
    m_compareSettings.m_compareX += ((double)dp.x()) / width();
Shinya Kitaoka 120a6e
  else if (m_compareSettings.m_dragCompareY)
Shinya Kitaoka 120a6e
    m_compareSettings.m_compareY -= ((double)dp.y()) / height();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_compareSettings.m_compareX = tcrop(m_compareSettings.m_compareX, 0.0, 1.0);
Shinya Kitaoka 120a6e
  m_compareSettings.m_compareY = tcrop(m_compareSettings.m_compareY, 0.0, 1.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::updateLoadbox(const TPoint &curPos) {
Shinya Kitaoka 120a6e
  TAffine aff = getImgToWidgetAffine();
Shinya Kitaoka 120a6e
  TRect r =
Shinya Kitaoka 120a6e
      m_flipbook
Shinya Kitaoka 120a6e
          ->getLoadbox();  // convert(aff*convert(m_flipbook->getLoadbox()));
Shinya Kitaoka 120a6e
  if (m_dragType == eDrawRect)
Shinya Kitaoka 120a6e
    r = convert(aff.inv() *
Shinya Kitaoka 120a6e
                convert(TRect(m_pressedMousePos,
Shinya Kitaoka 120a6e
                              curPos)));  // TRect(m_pressedMousePos, curPos);
Shinya Kitaoka 120a6e
  else if (m_dragType == eMoveRect)
Shinya Kitaoka 120a6e
    r = r + (TPoint(curPos.x, -curPos.y) - TPoint(m_pos.x(), -m_pos.y()));
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    double fac = sqrt(1.0 / fabs(aff.det()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_dragType & eMoveLeft) r.x0 += fac * (curPos.x - m_pos.x());
Shinya Kitaoka 120a6e
    if (m_dragType & eMoveRight) r.x1 += fac * (curPos.x - m_pos.x());
Shinya Kitaoka 120a6e
    if (m_dragType & eMoveDown) r.y1 -= fac * (curPos.y - m_pos.y());
Shinya Kitaoka 120a6e
    if (m_dragType & eMoveUp) r.y0 -= fac * (curPos.y - m_pos.y());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_flipbook->setLoadbox(r);  // convert(aff.inv() * convert(r)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Shinya Kitaoka 120a6e
void ImageViewer::updateCursor(const TPoint &curPos) {
Shinya Kitaoka 120a6e
  int dragType = getDragType(
Shinya Kitaoka 120a6e
      curPos,
Shinya Kitaoka 120a6e
      convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox())));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (dragType) {
Shinya Kitaoka 120a6e
  case eMoveRect:
Shinya Kitaoka 120a6e
    setCursor(Qt::SizeAllCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case eMoveLeft:
Shinya Kitaoka 120a6e
  case eMoveRight:
Shinya Kitaoka 120a6e
    setCursor(Qt::SizeHorCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case eMoveDown:
Shinya Kitaoka 120a6e
  case eMoveUp:
Shinya Kitaoka 120a6e
    setCursor(Qt::SizeVerCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case eMoveLeft | eMoveUp:
Shinya Kitaoka 120a6e
  case eMoveRight | eMoveDown:
Shinya Kitaoka 120a6e
    setCursor(Qt::SizeBDiagCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case eMoveLeft | eMoveDown:
Shinya Kitaoka 120a6e
  case eMoveRight | eMoveUp:
Shinya Kitaoka 120a6e
    setCursor(Qt::SizeFDiagCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    setCursor(Qt::ArrowCursor);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
shun-iwasawa a8f111
shun-iwasawa a8f111
void ImageViewer::showEvent(QShowEvent *) {
shun-iwasawa a8f111
  TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
shun-iwasawa a8f111
  bool ret = connect(sceneHandle, SIGNAL(preferenceChanged(const QString &)),
shun-iwasawa a8f111
                     this, SLOT(onPreferenceChanged(const QString &)));
shun-iwasawa a8f111
  onPreferenceChanged("ColorCalibration");
shun-iwasawa a8f111
  assert(ret);
shun-iwasawa a8f111
}
shun-iwasawa a8f111
shun-iwasawa a8f111
//---------------------------------------------------------------------------------------------
shun-iwasawa a8f111
shun-iwasawa a8f111
void ImageViewer::hideEvent(QHideEvent *) {
shun-iwasawa a8f111
  TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
shun-iwasawa a8f111
  if (sceneHandle) sceneHandle->disconnect(this);
shun-iwasawa a8f111
}
shun-iwasawa a8f111
shun-iwasawa a8f111
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! If middle button is pressed pan the image. Update current mouse position.
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::mouseMoveEvent(QMouseEvent *event) {
Jeremy Bullock 73a150
  if (!m_image) return;
manongjohn 2c447c
manongjohn 2c447c
  if (m_gestureActive && m_touchDevice == QTouchDevice::TouchScreen &&
manongjohn 2c447c
      !m_stylusUsed) {
manongjohn 2c447c
    return;
manongjohn 2c447c
  }
manongjohn 2c447c
shun_iwasawa 7c988d
  QPoint curQPos = event->pos() * getDevPixRatio();
shun_iwasawa 7c988d
shun_iwasawa 7c988d
  TPoint curPos = TPoint(curQPos.x(), curQPos.y());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_visualSettings.m_defineLoadbox && m_flipbook) {
Shinya Kitaoka 120a6e
    if (m_mouseButton == Qt::LeftButton)
Shinya Kitaoka 120a6e
      updateLoadbox(curPos);
Shinya Kitaoka 120a6e
    else if (m_mouseButton == Qt::MidButton)
shun_iwasawa 7c988d
      panQt(curQPos - m_pos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      updateCursor(curPos);
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
    event->ignore();
shun_iwasawa 7c988d
    m_pos = curQPos;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // setting the cursors
Shinya Kitaoka 120a6e
  if (!m_isColorModel) {
Shinya Kitaoka 120a6e
    // when the histogram window is opened, switch to the RGB picker tool
Shinya Kitaoka 120a6e
    if (m_isHistogramEnable && m_histogramPopup->isVisible())
Shinya Kitaoka 120a6e
      setToolCursor(this, ToolCursor::PickerRGB);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      setCursor(Qt::ArrowCursor);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_visualSettings.m_doCompare && m_mouseButton == Qt::NoButton) {
Shinya Kitaoka 120a6e
    if (fabs(curPos.x - width() * m_compareSettings.m_compareX) < 20)
Shinya Kitaoka 120a6e
      setToolCursor(this, ToolCursor::ScaleHCursor);
Shinya Kitaoka 120a6e
    else if (fabs((height() - curPos.y) -
Shinya Kitaoka 120a6e
                  height() * m_compareSettings.m_compareY) < 20)
Shinya Kitaoka 120a6e
      setToolCursor(this, ToolCursor::ScaleVCursor);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_compareSettings.m_dragCompareX || m_compareSettings.m_dragCompareY)
shun_iwasawa 7c988d
    dragCompare(curQPos - m_pos);
Shinya Kitaoka 120a6e
  else if (m_mouseButton == Qt::MidButton)
shun_iwasawa 7c988d
    panQt(curQPos - m_pos);
Shinya Kitaoka 120a6e
shun_iwasawa 7c988d
  m_pos = curQPos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // pick the color if the histogram popup is opened
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable && m_histogramPopup->isVisible() && !m_isColorModel) {
Shinya Kitaoka 120a6e
    // Rect Pick
Shinya Kitaoka 120a6e
    if (m_mouseButton == Qt::LeftButton &&
Shinya Kitaoka 120a6e
        (event->modifiers() & Qt::ControlModifier)) {
Shinya Kitaoka 120a6e
      if (!m_rectRGBPick && !m_visualSettings.m_defineLoadbox &&
Shinya Kitaoka 120a6e
          (abs(m_pos.x() - m_pressedMousePos.x) > 10 ||
Shinya Kitaoka 120a6e
           abs(m_pos.y() - m_pressedMousePos.y) > 10) &&
Shinya Kitaoka 120a6e
          !(m_compareSettings.m_dragCompareX ||
Shinya Kitaoka 120a6e
            m_compareSettings.m_dragCompareY) &&
Shinya Kitaoka 120a6e
          m_flipbook)
Shinya Kitaoka 120a6e
        m_rectRGBPick = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_rectRGBPick) {
Shinya Kitaoka 120a6e
        update();
shun-iwasawa d5045c
        // do not pick vector image while dragging as a portion of the red
shun-iwasawa d5045c
        // rubber band may affect the result
shun-iwasawa d5045c
        TImageP img = getPickedImage(m_pos);
shun-iwasawa d5045c
        if (img && img->raster()) rectPickColor();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
    pickColor(event);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_mouseButton == Qt::LeftButton && !m_isColorModel &&
Shinya Kitaoka 120a6e
      (event->modifiers() & Qt::AltModifier)) {
Shinya Kitaoka 120a6e
    if (!m_draggingZoomSelection && !m_visualSettings.m_defineLoadbox &&
Shinya Kitaoka 120a6e
        (abs(m_pos.x() - m_pressedMousePos.x) > 10 ||
Shinya Kitaoka 120a6e
         abs(m_pos.y() - m_pressedMousePos.y) > 10) &&
Shinya Kitaoka 120a6e
        !(m_compareSettings.m_dragCompareX ||
Shinya Kitaoka 120a6e
          m_compareSettings.m_dragCompareY) &&
Shinya Kitaoka 120a6e
        m_flipbook)
Shinya Kitaoka 120a6e
      m_draggingZoomSelection = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_draggingZoomSelection) update();
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_draggingZoomSelection = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_isColorModel && m_mouseButton == Qt::LeftButton) {
Shinya Kitaoka 120a6e
    event->ignore();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*! notify the color picked by rgb picker to palette controller
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::setPickedColorToStyleEditor(const TPixel32 &color) {
Shinya Kitaoka 120a6e
  // do not modify the style #0
Shinya Kitaoka 120a6e
  TPaletteHandle *ph =
Shinya Kitaoka 120a6e
      TApp::instance()->getPaletteController()->getCurrentPalette();
Shinya Kitaoka 120a6e
  if (ph->getStyleIndex() == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TApp::instance()->getPaletteController()->setColorSample(color);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
shun-iwasawa 099c01
shun-iwasawa 099c01
TImageP ImageViewer::getPickedImage(QPointF mousePos) {
shun-iwasawa 099c01
  bool cursorIsInSnapShot = false;
shun-iwasawa 099c01
  if (m_visualSettings.m_doCompare) {
shun-iwasawa 099c01
    if (m_compareSettings.m_compareY == ImagePainter::DefaultCompareValue)
shun-iwasawa 099c01
      cursorIsInSnapShot =
shun-iwasawa 099c01
          m_compareSettings.m_swapCompared ==
shun-iwasawa 099c01
          (mousePos.x() > width() * m_compareSettings.m_compareX);
shun-iwasawa 099c01
    else
shun-iwasawa 099c01
      cursorIsInSnapShot =
shun-iwasawa 099c01
          m_compareSettings.m_swapCompared ==
shun-iwasawa 099c01
          (height() - mousePos.y() > height() * m_compareSettings.m_compareY);
shun-iwasawa 099c01
  }
shun-iwasawa 099c01
  if (cursorIsInSnapShot)
shun-iwasawa 099c01
    return TImageCache::instance()->get(QString("TnzCompareImg"), false);
shun-iwasawa 481b59
  else if (m_orgImage)
shun-iwasawa 481b59
    return m_orgImage;
shun-iwasawa 099c01
  else
shun-iwasawa 099c01
    return m_image;
shun-iwasawa 099c01
}
shun-iwasawa 099c01
shun-iwasawa 099c01
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! rgb picking
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) {
Shinya Kitaoka 120a6e
  if (!m_isHistogramEnable) return;
Shinya Kitaoka 120a6e
  if (!m_histogramPopup->isVisible()) return;
Shinya Kitaoka 120a6e
shun-iwasawa 21c135
  QPointF curPos = event->localPos() * getDevPixRatio();
shun_iwasawa 7c988d
Shinya Kitaoka 120a6e
  // avoid to pick outside of the flip
shun-iwasawa 21c135
  if ((!m_image) || !rect().contains(curPos.toPoint())) {
Shinya Kitaoka 120a6e
    // throw transparent color
Shinya Kitaoka 120a6e
    m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1));
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 099c01
  TImageP img = getPickedImage(curPos);
shun-iwasawa 099c01
  if (!img) {
shun-iwasawa 099c01
    m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1));
shun-iwasawa 099c01
    return;
shun-iwasawa 099c01
  }
shun-iwasawa 099c01
shun-iwasawa f2e168
  StylePicker picker(this, img);
Shinya Kitaoka 120a6e
shun-iwasawa 21c135
  TPointD pos =
shun-iwasawa 21c135
      getViewAff().inv() * TPointD(curPos.x() - (qreal)(width()) / 2,
shun-iwasawa 21c135
                                   -curPos.y() + (qreal)(height()) / 2);
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TRectD imgRect   = (img->raster()) ? convert(TRect(img->raster()->getSize()))
shun-iwasawa 481b59
                                     : img->getBBox();
shun-iwasawa d5045c
  TPointD imagePos = (img->raster()) ? TPointD(0.5 * imgRect.getLx() + pos.x,
shun-iwasawa d5045c
                                               0.5 * imgRect.getLy() + pos.y)
shun-iwasawa d5045c
                                     : pos;
Shinya Kitaoka 120a6e
shun-iwasawa d5045c
  if (!imgRect.contains(imagePos)) {
shun-iwasawa d5045c
    // throw transparent color if picking outside of the image
shun-iwasawa d5045c
    m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1));
shun-iwasawa d5045c
  } else if (!img->raster()) {  // vector image
shun-iwasawa d5045c
    // For unknown reasons, glReadPixels is covering the entire window not the
shun-iwasawa d5045c
    // OpenGL widget.
shun-iwasawa d5045c
    QPointF winPos = event->windowPos() * getDevPixRatio();
shun-iwasawa d5045c
    TPointD mousePos =
shun-iwasawa d5045c
        TPointD(winPos.x(), (double)(window()->height()) - winPos.y());
shun-iwasawa d5045c
    TRectD area  = TRectD(mousePos.x, mousePos.y, mousePos.x, mousePos.y);
shun-iwasawa d5045c
    TPixel32 pix = picker.pickColor(area);
shun-iwasawa d5045c
    m_histogramPopup->updateInfo(pix, imagePos);
shun-iwasawa d5045c
    if (putValueToStyleEditor) setPickedColorToStyleEditor(pix);
shun-iwasawa 481b59
  } else {
luz paz 6454c4
    // for specifying pixel range on picking vector
shun-iwasawa 2d0135
    double scale2 = getViewAff().det();
shun-iwasawa 481b59
    TPixel32 pixForStyleEditor;
shun-iwasawa 481b59
shun-iwasawa 481b59
    if (img->raster()->getPixelSize() == 8)  // 16bpc raster
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      TPixel64 pix =
shun-iwasawa 481b59
          picker.pickColor16(pos + TPointD(-0.5, -0.5), 10.0, scale2);
shun-iwasawa 481b59
      // throw the picked color to the histogram
shun-iwasawa 481b59
      m_histogramPopup->updateInfo(pix, imagePos);
shun-iwasawa 481b59
      pixForStyleEditor = toPixel32(pix);
shun-iwasawa 481b59
    } else if (img->raster()->getPixelSize() ==
shun-iwasawa 481b59
               16)  // 32bpc floating point raster
shun-iwasawa 481b59
    {
shun-iwasawa 481b59
      TPixelF pix =
shun-iwasawa 481b59
          picker.pickColor32F(pos + TPointD(-0.5, -0.5), 10.0, scale2);
shun-iwasawa 481b59
      // throw the picked color to the histogram
shun-iwasawa 481b59
      m_histogramPopup->updateInfo(pix, imagePos);
shun-iwasawa 481b59
      pixForStyleEditor = toPixel32(pix);
shun-iwasawa 481b59
    } else {  // 8bpc raster
shun-iwasawa 481b59
      TPixel32 pix = picker.pickColor(pos + TPointD(-0.5, -0.5), 10.0, scale2);
shun-iwasawa 481b59
      // throw the picked color to the histogram
shun-iwasawa 481b59
      m_histogramPopup->updateInfo(pix, imagePos);
shun-iwasawa 481b59
      pixForStyleEditor = pix;
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // throw it to the style editor as well
shun-iwasawa 481b59
    if (putValueToStyleEditor) setPickedColorToStyleEditor(pixForStyleEditor);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*! rectangular rgb picking. The picked color will be an average of pixels in
Shinya Kitaoka 120a6e
 * specified rectangle
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::rectPickColor(bool putValueToStyleEditor) {
shun-iwasawa 099c01
  auto isRas32 = [this](TImageP img) -> bool {
shun-iwasawa 099c01
    TRasterImageP ri = img;
shun-iwasawa 21c135
    if (!ri) return false;
shun-iwasawa 21c135
    TRaster32P ras32 = ri->getRaster();
shun-iwasawa 21c135
    if (!ras32) return false;
shun-iwasawa 21c135
    return true;
shun-iwasawa 21c135
  };
shun-iwasawa 21c135
Shinya Kitaoka 120a6e
  if (!m_isHistogramEnable) return;
Shinya Kitaoka 120a6e
  if (!m_histogramPopup->isVisible()) return;
Shinya Kitaoka 120a6e
shun-iwasawa 099c01
  TImageP img = getPickedImage(m_pos);
shun-iwasawa 099c01
  if (!img) {
shun-iwasawa 099c01
    m_histogramPopup->updateAverageColor(TPixel32::Transparent);
shun-iwasawa 099c01
    return;
shun-iwasawa 099c01
  }
shun-iwasawa 099c01
shun-iwasawa f2e168
  StylePicker picker(this, img);
Shinya Kitaoka 120a6e
shun-iwasawa d5045c
  if (!img->raster()) {  // vector image
shun-iwasawa d5045c
    TPointD pressedWinPos = convert(m_pressedMousePos) + m_winPosMousePosOffset;
shun-iwasawa d5045c
    TPointD startPos      = TPointD(pressedWinPos.x,
shun-iwasawa 481b59
                                    (double)(window()->height()) - pressedWinPos.y);
shun-iwasawa d5045c
    TPointD currentWinPos =
shun-iwasawa d5045c
        TPointD(m_pos.x(), m_pos.y()) + m_winPosMousePosOffset;
shun-iwasawa d5045c
    TPointD endPos = TPointD(currentWinPos.x,
shun-iwasawa d5045c
                             (double)(window()->height()) - currentWinPos.y);
shun-iwasawa d5045c
    TRectD area    = TRectD(startPos, endPos);
shun-iwasawa d5045c
    area           = area.enlarge(-4, -4);
shun-iwasawa d5045c
    if (area.getLx() < 2 || area.getLy() < 2) {
shun-iwasawa d5045c
      m_histogramPopup->updateAverageColor(TPixel32::Transparent);
shun-iwasawa d5045c
      return;
shun-iwasawa d5045c
    }
shun-iwasawa d5045c
    TPixel32 pix = picker.pickColor(area);
shun-iwasawa d5045c
    // throw the picked color to the histogram
shun-iwasawa d5045c
    m_histogramPopup->updateAverageColor(pix);
shun-iwasawa d5045c
    // throw it to the style editor as well
shun-iwasawa d5045c
    if (putValueToStyleEditor) setPickedColorToStyleEditor(pix);
shun-iwasawa d5045c
    return;
shun-iwasawa d5045c
  }
shun-iwasawa d5045c
Shinya Kitaoka 120a6e
  TPoint startPos =
Shinya Kitaoka 120a6e
      TPoint(m_pressedMousePos.x, height() - 1 - m_pressedMousePos.y);
Shinya Kitaoka 120a6e
  TPoint endPos = TPoint(m_pos.x(), height() - 1 - m_pos.y());
Shinya Kitaoka 120a6e
  TRectD area   = TRectD(convert(startPos), convert(endPos));
Shinya Kitaoka 120a6e
  area          = area.enlarge(-1, -1);
Shinya Kitaoka 120a6e
  if (area.getLx() < 2 || area.getLy() < 2) {
Shinya Kitaoka 120a6e
    m_histogramPopup->updateAverageColor(TPixel32::Transparent);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa d5045c
  TPointD start = getViewAff().inv() *
shun-iwasawa d5045c
                  TPointD(startPos.x - width() / 2, startPos.y - height() / 2);
shun-iwasawa d5045c
  TPointD end = getViewAff().inv() *
shun-iwasawa d5045c
                TPointD(endPos.x - width() / 2, endPos.y - height() / 2);
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  TPixel32 pixForStyleEditor;
shun-iwasawa d5045c
  if (img->raster()->getPixelSize() == 8)  // 16bpc raster
shun-iwasawa d5045c
  {
shun-iwasawa d5045c
    TPixel64 pix = picker.pickAverageColor16(TRectD(start, end));
shun-iwasawa d5045c
    // throw the picked color to the histogram
shun-iwasawa d5045c
    m_histogramPopup->updateAverageColor(pix);
shun-iwasawa 481b59
    pixForStyleEditor = toPixel32(pix);
shun-iwasawa 481b59
  } else if (img->raster()->getPixelSize() ==
shun-iwasawa 481b59
             16)  // 32bpc floating point raster
shun-iwasawa 481b59
  {
shun-iwasawa 481b59
    TPixelF pix = picker.pickAverageColor32F(TRectD(start, end));
shun-iwasawa 481b59
    // throw the picked color to the histogram
shun-iwasawa 481b59
    m_histogramPopup->updateAverageColor(pix);
shun-iwasawa 481b59
    pixForStyleEditor = toPixel32(pix);
shun-iwasawa d5045c
  } else {  // 8bpc raster
shun-iwasawa d5045c
    TPixel32 pix = picker.pickAverageColor(TRectD(start, end));
shun-iwasawa d5045c
    // throw the picked color to the histogram
shun-iwasawa d5045c
    m_histogramPopup->updateAverageColor(pix);
shun-iwasawa 481b59
    pixForStyleEditor = pix;
shun-iwasawa d5045c
  }
shun-iwasawa 481b59
  // throw it to the style editor as well
shun-iwasawa 481b59
  if (putValueToStyleEditor) setPickedColorToStyleEditor(pixForStyleEditor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Set current position and current mouse button event.
Shinya Kitaoka 120a6e
                Ignore event, so access to parent mousePressEvent.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ImageViewer::getDragType(const TPoint &pos, const TRect &loadbox) {
Shinya Kitaoka 120a6e
  if (loadbox == TRect()) return eDrawRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int ret = 0, dx = std::min(abs(loadbox.x0 - pos.x), abs(loadbox.x1 - pos.x)),
Shinya Kitaoka 120a6e
      dy = std::min(abs(loadbox.y0 - pos.y), abs(loadbox.y1 - pos.y));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (dx > 10 && dy > 10)
Shinya Kitaoka 120a6e
    return (loadbox.contains(pos)) ? eMoveRect : eDrawRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (dx <= 10 && pos.y >= loadbox.y0 - 10 && pos.y <= loadbox.y1 + 10) {
Shinya Kitaoka 120a6e
    if (dx == abs(loadbox.x0 - pos.x))
Shinya Kitaoka 120a6e
      ret = eMoveLeft;
Shinya Kitaoka 120a6e
    else if (dx == abs(loadbox.x1 - pos.x))
Shinya Kitaoka 120a6e
      ret = eMoveRight;
Shinya Kitaoka 120a6e
  } else if (dy <= 10 && pos.x >= loadbox.x0 - 10 && pos.x <= loadbox.x1 + 10) {
Shinya Kitaoka 120a6e
    if (dy == abs(loadbox.y0 - pos.y))
Shinya Kitaoka 120a6e
      return eMoveDown;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return eMoveUp;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return eDrawRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (dy > 10) return ret;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return ret | (dy == (abs(loadbox.y0 - pos.y)) ? eMoveDown : eMoveUp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
void ImageViewer::mouseDoubleClickEvent(QMouseEvent *event) {
Jeremy Bullock 73a150
  if (!m_image) return;
manongjohn 2c447c
  // qDebug() << "[mouseDoubleClickEvent]";
manongjohn 2c447c
  if (m_gestureActive && !m_stylusUsed) {
manongjohn 2c447c
    m_gestureActive = false;
manongjohn 2c447c
    fitView();
manongjohn 2c447c
    return;
manongjohn 2c447c
  }
manongjohn 2c447c
Shinya Kitaoka 120a6e
  if (m_visualSettings.m_defineLoadbox && m_flipbook) {
Shinya Kitaoka 120a6e
    m_flipbook->setLoadbox(TRect());
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
    event->ignore();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::mousePressEvent(QMouseEvent *event) {
Jeremy Bullock 73a150
  if (!m_image) return;
manongjohn 2c447c
manongjohn 2c447c
  // qDebug() << "[mousePressEvent]";
manongjohn 2c447c
  if (m_gestureActive && m_touchDevice == QTouchDevice::TouchScreen &&
manongjohn 2c447c
      !m_stylusUsed) {
manongjohn 2c447c
    return;
manongjohn 2c447c
  }
manongjohn 2c447c
shun_iwasawa 7c988d
  m_pos                   = event->pos() * getDevPixRatio();
Shinya Kitaoka 120a6e
  m_pressedMousePos       = TPoint(m_pos.x(), m_pos.y());
Shinya Kitaoka 120a6e
  m_mouseButton           = event->button();
Shinya Kitaoka 120a6e
  m_draggingZoomSelection = false;
Shinya Kitaoka 120a6e
shun-iwasawa d5045c
  QPointF winPosMousePos = event->windowPos() * getDevPixRatio() - m_pos;
shun-iwasawa d5045c
  m_winPosMousePosOffset = TPointD(winPosMousePos.x(), winPosMousePos.y());
shun-iwasawa d5045c
Shinya Kitaoka 120a6e
  if (m_mouseButton != Qt::LeftButton) {
Shinya Kitaoka 120a6e
    event->ignore();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_visualSettings.m_defineLoadbox && m_flipbook)
Shinya Kitaoka 120a6e
    m_dragType = getDragType(
Shinya Kitaoka 120a6e
        m_pressedMousePos,
Shinya Kitaoka 120a6e
        convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox())));
Shinya Kitaoka 120a6e
  else if (m_visualSettings.m_doCompare) {
Shinya Kitaoka 120a6e
    if (fabs(m_pos.x() - width() * m_compareSettings.m_compareX) < 20) {
Shinya Kitaoka 120a6e
      m_compareSettings.m_dragCompareX = true;
Shinya Kitaoka 120a6e
      m_compareSettings.m_dragCompareY = false;
Shinya Kitaoka 120a6e
      m_compareSettings.m_compareY     = ImagePainter::DefaultCompareValue;
Shinya Kitaoka 120a6e
      update();
Shinya Kitaoka 120a6e
    } else if (fabs((height() - m_pos.y()) -
Shinya Kitaoka 120a6e
                    height() * m_compareSettings.m_compareY) < 20) {
Shinya Kitaoka 120a6e
      m_compareSettings.m_dragCompareY = true;
Shinya Kitaoka 120a6e
      m_compareSettings.m_dragCompareX = false;
Shinya Kitaoka 120a6e
      m_compareSettings.m_compareX     = ImagePainter::DefaultCompareValue;
Shinya Kitaoka 120a6e
      update();
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      m_compareSettings.m_dragCompareX = m_compareSettings.m_dragCompareY =
Shinya Kitaoka 120a6e
          false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // pick color and throw it to the style editor
Shinya Kitaoka 120a6e
  if (m_isHistogramEnable && m_histogramPopup->isVisible() && !m_isColorModel &&
Shinya Kitaoka 120a6e
      !(event->modifiers() & Qt::ControlModifier))  // if ctrl button is
Shinya Kitaoka 120a6e
                                                    // pressed, which means
Shinya Kitaoka 120a6e
                                                    // rectangular pick
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
    pickColor(event, true);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  event->ignore();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Reset current mouse position and current mouse button event.
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::mouseReleaseEvent(QMouseEvent *event) {
Jeremy Bullock 73a150
  if (!m_image) return;
Shinya Kitaoka 120a6e
  if (m_draggingZoomSelection && !m_visualSettings.m_defineLoadbox) {
Shinya Kitaoka 120a6e
    m_draggingZoomSelection = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int left, right, top, bottom;
Shinya Kitaoka 120a6e
    if (m_pos.x() < m_pressedMousePos.x)
Shinya Kitaoka 120a6e
      left = m_pos.x(), right = m_pressedMousePos.x;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      right = m_pos.x(), left = m_pressedMousePos.x;
Shinya Kitaoka 120a6e
    if (m_pos.y() < m_pressedMousePos.y)
Shinya Kitaoka 120a6e
      top = m_pos.y(), bottom = m_pressedMousePos.y;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      bottom = m_pos.y(), top = m_pressedMousePos.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    adaptView(QRect(QPoint(left, top), QPoint(right, bottom)));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_rectRGBPick) {
Shinya Kitaoka 120a6e
    // pick color in the rectangular region
Shinya Kitaoka 120a6e
    rectPickColor(true);
Shinya Kitaoka 120a6e
    // release the flag
Shinya Kitaoka 120a6e
    m_rectRGBPick = false;
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_pos                            = QPoint(0, 0);
Shinya Kitaoka 120a6e
  m_mouseButton                    = Qt::NoButton;
Shinya Kitaoka 120a6e
  m_compareSettings.m_dragCompareX = m_compareSettings.m_dragCompareY = false;
Shinya Kitaoka 120a6e
manongjohn 2c447c
  m_gestureActive = false;
manongjohn 2c447c
  m_zooming       = false;
manongjohn 2c447c
  m_panning       = false;
manongjohn 2c447c
  m_stylusUsed    = false;
manongjohn 2c447c
Shinya Kitaoka 120a6e
  event->ignore();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Apply zoom.
shun-iwasawa b766d1
 */
Shinya Kitaoka 120a6e
void ImageViewer::wheelEvent(QWheelEvent *event) {
Jeremy Bullock 73a150
  if (!m_image) return;
Shinya Kitaoka 120a6e
  if (event->orientation() == Qt::Horizontal) return;
manongjohn 2c447c
  int delta = 0;
manongjohn 2c447c
  switch (event->source()) {
manongjohn 2c447c
  case Qt::MouseEventNotSynthesized: {
manongjohn 2c447c
    if (event->modifiers() & Qt::AltModifier)
manongjohn 2c447c
      delta = event->angleDelta().x();
manongjohn 2c447c
    else
manongjohn 2c447c
      delta = event->angleDelta().y();
manongjohn 2c447c
    break;
manongjohn 2c447c
  }
manongjohn 2c447c
manongjohn 2c447c
  case Qt::MouseEventSynthesizedBySystem: {
manongjohn 2c447c
    QPoint numPixels  = event->pixelDelta();
manongjohn 2c447c
    QPoint numDegrees = event->angleDelta() / 8;
manongjohn 2c447c
    if (!numPixels.isNull()) {
manongjohn 2c447c
      delta = event->pixelDelta().y();
manongjohn 2c447c
    } else if (!numDegrees.isNull()) {
manongjohn 2c447c
      QPoint numSteps = numDegrees / 15;
manongjohn 2c447c
      delta           = numSteps.y();
manongjohn 2c447c
    }
manongjohn 2c447c
    break;
manongjohn 2c447c
  }
manongjohn 2c447c
manongjohn 2c447c
  default:  // Qt::MouseEventSynthesizedByQt,
manongjohn 2c447c
            // Qt::MouseEventSynthesizedByApplication
shun-iwasawa b766d1
  {
shun-iwasawa b766d1
    std::cout << "not supported event: Qt::MouseEventSynthesizedByQt, "
shun-iwasawa b766d1
                 "Qt::MouseEventSynthesizedByApplication"
shun-iwasawa b766d1
              << std::endl;
shun-iwasawa b766d1
    break;
shun-iwasawa b766d1
  }
manongjohn 2c447c
manongjohn 2c447c
  }  // end switch
manongjohn 2c447c
manongjohn 2c447c
  if (abs(delta) > 0) {
manongjohn 2c447c
    if ((m_gestureActive == true &&
manongjohn 2c447c
         m_touchDevice == QTouchDevice::TouchScreen) ||
manongjohn 2c447c
        m_gestureActive == false) {
manongjohn 2c447c
      int delta = event->delta() > 0 ? 120 : -120;
manongjohn 2c447c
      QPoint center(event->pos().x() * getDevPixRatio() - width() / 2,
manongjohn 2c447c
                    -event->pos().y() * getDevPixRatio() + height() / 2);
manongjohn 2c447c
      zoomQt(center, exp(0.001 * delta));
manongjohn 2c447c
    }
manongjohn 2c447c
  }
manongjohn 2c447c
  event->accept();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::swapCompared() {
Shinya Kitaoka 120a6e
  m_compareSettings.m_swapCompared = !m_compareSettings.m_swapCompared;
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::setViewAff(TAffine viewAff) {
Shinya Kitaoka 120a6e
  m_viewAff = viewAff;
Shinya Kitaoka 120a6e
  update();
Shinya Kitaoka 120a6e
  if (m_flipbook && m_flipbook->getPreviewedFx())
Shinya Kitaoka 120a6e
    // Update the observable fx region
Shinya Kitaoka 120a6e
    m_flipbook->schedulePreviewedFxUpdate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::resetView() { zoomQt(false, true); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::fitView() {
Shinya Kitaoka 120a6e
  if (!m_image) return;
Shinya Kitaoka 120a6e
  TRect imgBounds(getImageBounds(m_image));
Shinya Kitaoka 120a6e
  adaptView(imgBounds, imgBounds);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
luz paz 6454c4
/*! Update image viewer, reset current matrix transformation, current position
Shinya Kitaoka 120a6e
                and update view.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void ImageViewer::updateImageViewer() {
Shinya Kitaoka 120a6e
  setViewAff(TAffine());
Shinya Kitaoka 120a6e
  m_pos = QPoint(0, 0);
Shinya Kitaoka 120a6e
  update();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine ImageViewer::getImgToWidgetAffine() const {
Shinya Kitaoka 120a6e
  assert(m_image);
Shinya Kitaoka 120a6e
  return getImgToWidgetAffine(getImageBoundsD(m_image));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns the affine transform from image reference to widget's pixel one.
Shinya Kitaoka 120a6e
TAffine ImageViewer::getImgToWidgetAffine(const TRectD &geom) const {
Shinya Kitaoka 120a6e
  TPointD geomCenter((geom.x0 + geom.x1) * 0.5, (geom.y0 + geom.y1) * 0.5);
Shinya Kitaoka 120a6e
shun_iwasawa 0e4be6
  QRect widGeom(rect());
shun_iwasawa 0e4be6
Shinya Kitaoka 120a6e
  TPointD viewerCenter((widGeom.left() + widGeom.right() + 1) * 0.5,
Shinya Kitaoka 120a6e
                       (widGeom.top() + widGeom.bottom() + 1) * 0.5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return TAffine(TAffine(1.0, 0.0, 0.0, 0.0, -1.0, height()) *
Shinya Kitaoka 120a6e
                 TTranslation(viewerCenter) * m_viewAff *
Shinya Kitaoka 120a6e
                 TTranslation(-geomCenter));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Adapts image viewer's affine to display the passed image rect at maximized
Shinya Kitaoka 120a6e
//! ratio
Shinya Kitaoka 120a6e
void ImageViewer::adaptView(const TRect &imgRect, const TRect &viewRect) {
shun_iwasawa 0e4be6
  QRect viewerRect(rect());
Toshihiro Shimizu 890ddd
shun-iwasawa 2e5dc5
  if (viewerRect.isEmpty()) return;
shun-iwasawa 2e5dc5
Shinya Kitaoka 120a6e
  double imageScale = std::min(viewerRect.width() / (double)viewRect.getLx(),
Shinya Kitaoka 120a6e
                               viewerRect.height() / (double)viewRect.getLy());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD viewRectCenter((viewRect.x0 + viewRect.x1 + 1) * 0.5,
Shinya Kitaoka 120a6e
                         (viewRect.y0 + viewRect.y1 + 1) * 0.5);
Shinya Kitaoka 120a6e
  TPointD imgRectCenter((imgRect.x0 + imgRect.x1 + 1) * 0.5,
Shinya Kitaoka 120a6e
                        (imgRect.y0 + imgRect.y1 + 1) * 0.5);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine newViewAff(TScale(imageScale, imageScale) *
Shinya Kitaoka 120a6e
                     TTranslation(imgRectCenter - viewRectCenter));
Shinya Kitaoka 120a6e
  setViewAff(newViewAff);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Adapts image viewer's affine to display the passed viewer rect at maximized
Shinya Kitaoka 120a6e
//! ratio
Shinya Kitaoka 120a6e
void ImageViewer::adaptView(const QRect &geomRect) {
Shinya Kitaoka 120a6e
  if (!m_image) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the rect in image reference and call the associated adaptView
Shinya Kitaoka 120a6e
  TRect imgBounds(getImageBounds(m_image));
Shinya Kitaoka 120a6e
  TRectD imgBoundsD(imgBounds.x0, imgBounds.y0, imgBounds.x1 + 1,
Shinya Kitaoka 120a6e
                    imgBounds.y1 + 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD geomRectD(geomRect.left(), geomRect.top(), geomRect.right() + 1,
Shinya Kitaoka 120a6e
                   geomRect.bottom() + 1);
Shinya Kitaoka 120a6e
  TRectD viewRectD(getImgToWidgetAffine().inv() * geomRectD);
Shinya Kitaoka 120a6e
  TRect viewRect(tfloor(viewRectD.x0), tfloor(viewRectD.y0),
Shinya Kitaoka 120a6e
                 tceil(viewRectD.x1) - 1, tceil(viewRectD.y1) - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  adaptView(imgBounds, viewRect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageViewer::doSwapBuffers() { glFlush(); }
Shinya Kitaoka 210a8a
Shinya Kitaoka 210a8a
void ImageViewer::changeSwapBehavior(bool enable) {
shun_iwasawa 7c988d
  // do nothing for now as setUpdateBehavior is not available with QGLWidget
shun_iwasawa 7c988d
  // setUpdateBehavior(enable ? PartialUpdate : NoPartialUpdate);
Shinya Kitaoka 210a8a
}
Shinya Kitaoka 210a8a
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa d5045c
void ImageViewer::invalidateCompHisto() {
shun-iwasawa d5045c
  if (!m_isHistogramEnable || !m_histogramPopup) return;
shun-iwasawa d5045c
  m_histogramPopup->invalidateCompHisto();
shun-iwasawa d5045c
}
shun-iwasawa d5045c
shun-iwasawa d5045c
//-----------------------------------------------------------------------------
shun-iwasawa d5045c
Shinya Kitaoka 120a6e
void ImageViewer::keyPressEvent(QKeyEvent *event) {
Shinya Kitaoka 120a6e
  if (FlipZoomer(this).exec(event)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ImageViewerShortcutReceiver(m_flipbook).exec(event);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
shun-iwasawa 388550
shun-iwasawa 388550
void ImageViewer::onContextAboutToBeDestroyed() {
shun-iwasawa 388550
  if (!m_lutCalibrator) return;
shun-iwasawa 388550
  makeCurrent();
shun-iwasawa 388550
  m_lutCalibrator->cleanup();
shun-iwasawa 388550
  doneCurrent();
shun-iwasawa 034d17
  disconnect(context(), SIGNAL(aboutToBeDestroyed()), this,
shun-iwasawa 034d17
             SLOT(onContextAboutToBeDestroyed()));
shun-iwasawa 388550
}
shun-iwasawa 388550
shun-iwasawa a8f111
//-----------------------------------------------------------------------------
shun-iwasawa a8f111
shun-iwasawa a8f111
void ImageViewer::onPreferenceChanged(const QString &prefName) {
shun-iwasawa a8f111
  if (prefName == "ColorCalibration") {
shun-iwasawa a8f111
    if (Preferences::instance()->isColorCalibrationEnabled()) {
shun-iwasawa 034d17
      // if the window is so shriked that the gl widget is empty,
shun-iwasawa 034d17
      // showEvent can be called before creating the context.
shun-iwasawa 034d17
      if (!context()) return;
shun-iwasawa a8f111
      makeCurrent();
shun-iwasawa a8f111
      if (!m_lutCalibrator)
shun-iwasawa a8f111
        m_lutCalibrator = new LutCalibrator();
shun-iwasawa a8f111
      else
shun-iwasawa a8f111
        m_lutCalibrator->cleanup();
shun-iwasawa a8f111
      m_lutCalibrator->initialize();
shun-iwasawa a8f111
      connect(context(), SIGNAL(aboutToBeDestroyed()), this,
shun-iwasawa a8f111
              SLOT(onContextAboutToBeDestroyed()));
shun-iwasawa 215a5b
      if (m_lutCalibrator->isValid() && !m_fbo) {
shun-iwasawa 215a5b
        if (Preferences::instance()->is30bitDisplayEnabled()) {
shun-iwasawa 215a5b
          QOpenGLFramebufferObjectFormat format;
shun-iwasawa 215a5b
          format.setInternalTextureFormat(TGL_TexFmt10);
shun-iwasawa 215a5b
          m_fbo = new QOpenGLFramebufferObject(width(), height(), format);
shun-iwasawa 215a5b
        } else  // normally, initialize with GL_RGBA8 format
shun-iwasawa 215a5b
          m_fbo = new QOpenGLFramebufferObject(width(), height());
shun-iwasawa 215a5b
      }
shun-iwasawa a8f111
      doneCurrent();
shun-iwasawa a8f111
    }
shun-iwasawa a8f111
    update();
shun-iwasawa a8f111
  }
shun-iwasawa a8f111
}
shun-iwasawa a8f111
manongjohn 2c447c
//------------------------------------------------------------------
manongjohn 2c447c
manongjohn 2c447c
void ImageViewer::tabletEvent(QTabletEvent *e) {
manongjohn 2c447c
  // qDebug() << "[tabletEvent]";
manongjohn 2c447c
  if (e->type() == QTabletEvent::TabletPress) {
manongjohn 2c447c
    m_stylusUsed = e->pointerType() ? true : false;
manongjohn 2c447c
  } else if (e->type() == QTabletEvent::TabletRelease) {
manongjohn 2c447c
    m_stylusUsed = false;
manongjohn 2c447c
  }
manongjohn 2c447c
manongjohn 2c447c
  e->accept();
manongjohn 2c447c
}
manongjohn 2c447c
manongjohn 2c447c
//------------------------------------------------------------------
manongjohn 2c447c
manongjohn 2c447c
void ImageViewer::gestureEvent(QGestureEvent *e) {
manongjohn 2c447c
  // qDebug() << "[gestureEvent]";
manongjohn 2c447c
  m_gestureActive = false;
manongjohn 2c447c
  if (QGesture *swipe = e->gesture(Qt::SwipeGesture)) {
manongjohn 2c447c
    m_gestureActive = true;
manongjohn 2c447c
  } else if (QGesture *pan = e->gesture(Qt::PanGesture)) {
manongjohn 2c447c
    m_gestureActive = true;
manongjohn 2c447c
  }
manongjohn 2c447c
  if (QGesture *pinch = e->gesture(Qt::PinchGesture)) {
manongjohn 2c447c
    QPinchGesture *gesture = static_cast<qpinchgesture *="">(pinch);</qpinchgesture>
manongjohn 2c447c
    QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
manongjohn 2c447c
    QPoint firstCenter                     = gesture->centerPoint().toPoint();
manongjohn 2c447c
    if (m_touchDevice == QTouchDevice::TouchScreen)
manongjohn 2c447c
      firstCenter = mapFromGlobal(firstCenter);
manongjohn 2c447c
manongjohn 2c447c
    if (gesture->state() == Qt::GestureStarted) {
manongjohn 2c447c
      m_gestureActive = true;
manongjohn 2c447c
    } else if (gesture->state() == Qt::GestureFinished) {
manongjohn 2c447c
      m_gestureActive = false;
manongjohn 2c447c
      m_zooming       = false;
manongjohn 2c447c
      m_scaleFactor   = 0.0;
manongjohn 2c447c
    } else {
manongjohn 2c447c
      if (changeFlags & QPinchGesture::ScaleFactorChanged) {
manongjohn 2c447c
        double scaleFactor = gesture->scaleFactor();
manongjohn 2c447c
        // the scale factor makes for too sensitive scaling
manongjohn 2c447c
        // divide the change in half
manongjohn 2c447c
        if (scaleFactor > 1) {
manongjohn 2c447c
          double decimalValue = scaleFactor - 1;
manongjohn 2c447c
          decimalValue /= 1.5;
manongjohn 2c447c
          scaleFactor = 1 + decimalValue;
manongjohn 2c447c
        } else if (scaleFactor < 1) {
manongjohn 2c447c
          double decimalValue = 1 - scaleFactor;
manongjohn 2c447c
          decimalValue /= 1.5;
manongjohn 2c447c
          scaleFactor = 1 - decimalValue;
manongjohn 2c447c
        }
manongjohn 2c447c
        if (!m_zooming) {
manongjohn 2c447c
          double delta = scaleFactor - 1;
manongjohn 2c447c
          m_scaleFactor += delta;
manongjohn 2c447c
          if (m_scaleFactor > .2 || m_scaleFactor < -.2) {
manongjohn 2c447c
            m_zooming = true;
manongjohn 2c447c
          }
manongjohn 2c447c
        }
manongjohn 2c447c
        if (m_zooming) {
manongjohn 2c447c
          const QPoint center(
manongjohn 2c447c
              firstCenter.x() * getDevPixRatio() - width() / 2,
manongjohn 2c447c
              -firstCenter.y() * getDevPixRatio() + height() / 2);
manongjohn 2c447c
          zoomQt(center, scaleFactor);
manongjohn 2c447c
          m_panning = false;
manongjohn 2c447c
        }
manongjohn 2c447c
        m_gestureActive = true;
manongjohn 2c447c
      }
manongjohn 2c447c
manongjohn 2c447c
      if (changeFlags & QPinchGesture::CenterPointChanged) {
manongjohn 2c447c
        QPointF centerDelta = (gesture->centerPoint() * getDevPixRatio()) -
manongjohn 2c447c
                              (gesture->lastCenterPoint() * getDevPixRatio());
manongjohn 2c447c
        if (centerDelta.manhattanLength() > 1) {
manongjohn 2c447c
          // panQt(centerDelta.toPoint());
manongjohn 2c447c
        }
manongjohn 2c447c
        m_gestureActive = true;
manongjohn 2c447c
      }
manongjohn 2c447c
    }
manongjohn 2c447c
  }
manongjohn 2c447c
  e->accept();
manongjohn 2c447c
}
manongjohn 2c447c
manongjohn 2c447c
void ImageViewer::touchEvent(QTouchEvent *e, int type) {
manongjohn 2c447c
  // qDebug() << "[touchEvent]";
manongjohn 2c447c
  if (type == QEvent::TouchBegin) {
manongjohn 2c447c
    m_touchActive   = true;
manongjohn 2c447c
    m_firstPanPoint = e->touchPoints().at(0).pos();
manongjohn 2c447c
    // obtain device type
manongjohn 2c447c
    m_touchDevice = e->device()->type();
manongjohn 2c447c
  } else if (m_touchActive) {
manongjohn 2c447c
    // touchpads must have 2 finger panning for tools and navigation to be
manongjohn 2c447c
    // functional on other devices, 1 finger panning is preferred
manongjohn 2c447c
    if ((e->touchPoints().count() == 2 &&
manongjohn 2c447c
         m_touchDevice == QTouchDevice::TouchPad) ||
manongjohn 2c447c
        (e->touchPoints().count() == 1 &&
manongjohn 2c447c
         m_touchDevice == QTouchDevice::TouchScreen)) {
manongjohn 2c447c
      QTouchEvent::TouchPoint panPoint = e->touchPoints().at(0);
manongjohn 2c447c
      if (!m_panning) {
manongjohn 2c447c
        QPointF deltaPoint = panPoint.pos() - m_firstPanPoint;
manongjohn 2c447c
        // minimize accidental and jerky zooming/rotating during 2 finger
manongjohn 2c447c
        // panning
manongjohn 2c447c
        if ((deltaPoint.manhattanLength() > 100) && !m_zooming) {
manongjohn 2c447c
          m_panning = true;
manongjohn 2c447c
        }
manongjohn 2c447c
      }
manongjohn 2c447c
      if (m_panning) {
manongjohn 2c447c
        QPoint curPos      = panPoint.pos().toPoint() * getDevPixRatio();
manongjohn 2c447c
        QPoint lastPos     = panPoint.lastPos().toPoint() * getDevPixRatio();
manongjohn 2c447c
        QPoint centerDelta = curPos - lastPos;
manongjohn 2c447c
        panQt(centerDelta);
manongjohn 2c447c
      }
manongjohn 2c447c
    }
manongjohn 2c447c
  }
manongjohn 2c447c
  if (type == QEvent::TouchEnd || type == QEvent::TouchCancel) {
manongjohn 2c447c
    m_touchActive = false;
manongjohn 2c447c
    m_panning     = false;
manongjohn 2c447c
  }
manongjohn 2c447c
  e->accept();
manongjohn 2c447c
}
manongjohn 2c447c
manongjohn 2c447c
bool ImageViewer::event(QEvent *e) {
manongjohn 2c447c
  /*
manongjohn 2c447c
  switch (e->type()) {
manongjohn 2c447c
  case QEvent::TabletPress: {
manongjohn 2c447c
  QTabletEvent *te = static_cast<qtabletevent *="">(e);</qtabletevent>
manongjohn 2c447c
  qDebug() << "[event] TabletPress: pointerType(" << te->pointerType()
manongjohn 2c447c
  << ") device(" << te->device() << ")";
manongjohn 2c447c
  } break;
manongjohn 2c447c
  case QEvent::TabletRelease:
manongjohn 2c447c
  qDebug() << "[event] TabletRelease";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::TouchBegin:
manongjohn 2c447c
  qDebug() << "[event] TouchBegin";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::TouchEnd:
manongjohn 2c447c
  qDebug() << "[event] TouchEnd";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::TouchCancel:
manongjohn 2c447c
  qDebug() << "[event] TouchCancel";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::MouseButtonPress:
manongjohn 2c447c
  qDebug() << "[event] MouseButtonPress";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::MouseButtonDblClick:
manongjohn 2c447c
  qDebug() << "[event] MouseButtonDblClick";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::MouseButtonRelease:
manongjohn 2c447c
  qDebug() << "[event] MouseButtonRelease";
manongjohn 2c447c
  break;
manongjohn 2c447c
  case QEvent::Gesture:
manongjohn 2c447c
  qDebug() << "[event] Gesture";
manongjohn 2c447c
  break;
manongjohn 2c447c
  default:
manongjohn 2c447c
  break;
manongjohn 2c447c
  }
manongjohn 2c447c
  */
manongjohn 2c447c
shun-iwasawa b766d1
  if (e->type() == QEvent::Gesture && CommandManager::instance()
shun-iwasawa b766d1
                                          ->getAction(MI_TouchGestureControl)
shun-iwasawa b766d1
                                          ->isChecked()) {
manongjohn 2c447c
    gestureEvent(static_cast<qgestureevent *="">(e));</qgestureevent>
manongjohn 2c447c
    return true;
manongjohn 2c447c
  }
manongjohn 2c447c
  if ((e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchEnd ||
manongjohn 2c447c
       e->type() == QEvent::TouchCancel || e->type() == QEvent::TouchUpdate) &&
manongjohn 2c447c
      CommandManager::instance()
manongjohn 2c447c
          ->getAction(MI_TouchGestureControl)
manongjohn 2c447c
          ->isChecked()) {
manongjohn 2c447c
    touchEvent(static_cast<qtouchevent *="">(e), e->type());</qtouchevent>
manongjohn 2c447c
    m_gestureActive = true;
manongjohn 2c447c
    return true;
manongjohn 2c447c
  }
manongjohn 2c447c
  return GLWidgetForHighDpi::event(e);
manongjohn 2c447c
}
manongjohn 2c447c
shun-iwasawa 388550
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! load image from history
shun-iwasawa b766d1
 */
Shinya Kitaoka d1f6c4
class LoadRecentFlipbookImagesCommandHandler final : public MenuItemHandler {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  LoadRecentFlipbookImagesCommandHandler()
Shinya Kitaoka 120a6e
      : MenuItemHandler(MI_LoadRecentImage) {}
Shinya Kitaoka 473e70
  void execute() override {
Shinya Kitaoka 120a6e
    QAction *act = CommandManager::instance()->getAction(MI_LoadRecentImage);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    /*--- 右クリックで呼ばれないとここにWidgetが入らない ---*/
Shinya Kitaoka 120a6e
    FlipBook *flip = qobject_cast<flipbook *="">(act->parentWidget());</flipbook>
Shinya Kitaoka 120a6e
    if (!flip) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    DVMenuAction *menu = dynamic_cast<dvmenuaction *="">(act->menu());</dvmenuaction>
Shinya Kitaoka 120a6e
    int index          = menu->getTriggeredActionIndex();
Shinya Kitaoka 120a6e
    QString path =
Shinya Kitaoka 120a6e
        RecentFiles::instance()->getFilePath(index, RecentFiles::Flip);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TFilePath fp(path.toStdWString());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    /*--- shrinkは1でロードする ---*/
Shinya Kitaoka 120a6e
    ::viewFile(fp, -1, -1, -1, 1, 0, flip, false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    RecentFiles::instance()->moveFilePath(index, 0, RecentFiles::Flip);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
} loadRecentFlipbookImagesCommandHandler;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! clear the history
shun-iwasawa b766d1
 */
Shinya Kitaoka d1f6c4
class ClearRecentFlipbookImagesCommandHandler final : public MenuItemHandler {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ClearRecentFlipbookImagesCommandHandler()
Shinya Kitaoka 120a6e
      : MenuItemHandler(MI_ClearRecentImage) {}
Shinya Kitaoka 473e70
  void execute() override {
Shinya Kitaoka 120a6e
    RecentFiles::instance()->clearRecentFilesList(RecentFiles::Flip);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
} clearRecentFlipbookImagesCommandHandler;