00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kis_canvas2.h"
00021
00022 #include <QWidget>
00023 #include <QTime>
00024 #include <QLabel>
00025 #include <QMouseEvent>
00026
00027 #include <kis_debug.h>
00028
00029 #include "KoUnit.h"
00030 #include "KoZoomHandler.h"
00031 #include "KoViewConverter.h"
00032 #include "KoShapeManager.h"
00033 #include "colorprofiles/KoIccColorProfile.h"
00034 #include "KoColorSpaceRegistry.h"
00035 #include "KoCanvasController.h"
00036 #include "KoDocument.h"
00037 #include "KoZoomAction.h"
00038 #include "KoToolProxy.h"
00039 #include "KoSelection.h"
00040
00041 #include "kis_prescaled_projection.h"
00042 #include "kis_image.h"
00043 #include "kis_doc2.h"
00044 #include "flake/kis_shape_layer.h"
00045 #include "kis_canvas_resource_provider.h"
00046 #include "kis_view2.h"
00047 #include "kis_config.h"
00048 #include "kis_config_notifier.h"
00049 #include "kis_abstract_canvas_widget.h"
00050 #include "kis_qpainter_canvas.h"
00051 #include "kis_group_layer.h"
00052 #include "flake/kis_shape_controller.h"
00053 #include "kis_layer_manager.h"
00054 #include "kis_selection.h"
00055 #include "kis_selection_component.h"
00056 #include "flake/kis_shape_selection.h"
00057
00058 #include "opengl/kis_opengl_canvas2.h"
00059 #include "opengl/kis_opengl_image_textures.h"
00060 #ifdef HAVE_OPENGL
00061 #include <QGLFormat>
00062 #endif
00063 #include "kis_projection_cache.h"
00064
00065 class KisCanvas2::KisCanvas2Private
00066 {
00067
00068 public:
00069
00070 KisCanvas2Private(KoCanvasBase * parent, KoViewConverter * viewConverter, KisView2 * view)
00071 : viewConverter(viewConverter)
00072 , view(view)
00073 , canvasWidget(0)
00074 , shapeManager(new KoShapeManager(parent))
00075 , monitorProfile(0)
00076 , currentCanvasIsOpenGL(false)
00077 , currentCanvasUsesOpenGLShaders(false)
00078 , toolProxy(new KoToolProxy(parent)) {
00079 }
00080
00081 ~KisCanvas2Private() {
00082 delete shapeManager;
00083 delete toolProxy;
00084 }
00085
00086 KoViewConverter * viewConverter;
00087 KisView2 * view;
00088 KisAbstractCanvasWidget * canvasWidget;
00089 KoShapeManager * shapeManager;
00090 KoColorProfile * monitorProfile;
00091 bool currentCanvasIsOpenGL;
00092 bool currentCanvasUsesOpenGLShaders;
00093 KoToolProxy * toolProxy;
00094 QPoint documentOffset;
00095 KoShapeControllerBase * sc;
00096 #ifdef HAVE_OPENGL
00097 KisOpenGLImageTexturesSP openGLImageTextures;
00098 #endif
00099 KisPrescaledProjectionSP prescaledProjection;
00100 };
00101
00102 KisCanvas2::KisCanvas2(KoViewConverter * viewConverter, KisView2 * view, KoShapeControllerBase * sc)
00103 : KoCanvasBase(sc)
00104 , m_d(new KisCanvas2Private(this, viewConverter, view))
00105 {
00106 createCanvas();
00107 connect(view->canvasController(), SIGNAL(moveDocumentOffset(const QPoint&)), SLOT(documentOffsetMoved(const QPoint&)));
00108 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
00109 connect(this, SIGNAL(canvasDestroyed(QWidget *)), m_d->view, SLOT(slotCanvasDestroyed(QWidget *)));
00110 }
00111
00112 KisCanvas2::~KisCanvas2()
00113 {
00114 delete m_d;
00115 }
00116
00117 void KisCanvas2::setCanvasWidget(QWidget * widget)
00118 {
00119 KisAbstractCanvasWidget * tmp = dynamic_cast<KisAbstractCanvasWidget*>(widget);
00120 Q_ASSERT_X(tmp, "setCanvasWidget", "Cannot cast the widget to a KisAbstractCanvasWidget");
00121 emit canvasDestroyed(widget);
00122 m_d->canvasWidget = tmp;
00123 widget->setAutoFillBackground(false);
00124 widget->setAttribute(Qt::WA_OpaquePaintEvent);
00125 widget->setMouseTracking(true);
00126 widget->setAcceptDrops(true);
00127 KoCanvasController *controller = canvasController();
00128 if (controller) {
00129 Q_ASSERT(controller->canvas() == this);
00130
00131 controller->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00132 controller->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00133
00134 controller->changeCanvasWidget(widget);
00135 }
00136 }
00137
00138 void KisCanvas2::gridSize(qreal *horizontal, qreal *vertical) const
00139 {
00140 Q_ASSERT(horizontal);
00141 Q_ASSERT(vertical);
00142 *horizontal = m_d->view->document()->gridData().gridX();
00143 *vertical = m_d->view->document()->gridData().gridY();
00144 }
00145
00146 bool KisCanvas2::snapToGrid() const
00147 {
00148 return m_d->view->document()->gridData().snapToGrid();
00149 }
00150
00151 void KisCanvas2::addCommand(QUndoCommand *command)
00152 {
00153 m_d->view->koDocument()->addCommand(command);
00154 }
00155
00156 void KisCanvas2::startMacro(const QString &title)
00157 {
00158 m_d->view->koDocument()->beginMacro(title);
00159 }
00160
00161 void KisCanvas2::stopMacro()
00162 {
00163 m_d->view->koDocument()->endMacro();
00164 }
00165
00166 KoShapeManager* KisCanvas2::shapeManager() const
00167 {
00168 if (!m_d->view) return m_d->shapeManager;
00169 if (!m_d->view->layerManager()) return m_d->shapeManager;
00170
00171 KisLayerSP activeLayer = m_d->view->layerManager()->activeLayer();
00172 if (activeLayer) {
00173 KisShapeLayer * shapeLayer = dynamic_cast<KisShapeLayer*>(activeLayer.data());
00174 if (shapeLayer) {
00175 return shapeLayer->shapeManager();
00176 }
00177 if (activeLayer->selection() && activeLayer->selection()->hasShapeSelection()) {
00178 KoShapeManager* m = static_cast<KisShapeSelection*>(activeLayer->selection()->shapeSelection())->shapeManager();
00179 return m;
00180
00181 }
00182 }
00183 return m_d->shapeManager;
00184 }
00185
00186 KoShapeManager * KisCanvas2::globalShapeManager() const
00187 {
00188 return m_d->shapeManager;
00189 }
00190
00191 void KisCanvas2::updateCanvas(const QRectF& rc)
00192 {
00193
00194
00195 QRect vRect = viewRectFromDoc(rc);
00196 if (!vRect.isEmpty()) {
00197 m_d->canvasWidget->widget()->update(vRect);
00198 }
00199 }
00200
00201 void KisCanvas2::updateInputMethodInfo()
00202 {
00203
00204 }
00205
00206 const KoViewConverter* KisCanvas2::viewConverter() const
00207 {
00208 return m_d->viewConverter;
00209 }
00210
00211 QWidget* KisCanvas2::canvasWidget()
00212 {
00213 return m_d->canvasWidget->widget();
00214 }
00215
00216 const QWidget* KisCanvas2::canvasWidget() const
00217 {
00218 return m_d->canvasWidget->widget();
00219 }
00220
00221
00222 KoUnit KisCanvas2::unit() const
00223 {
00224 return KoUnit(KoUnit::Pixel);
00225 }
00226
00227 KoToolProxy * KisCanvas2::toolProxy() const
00228 {
00229 return m_d->toolProxy;
00230 }
00231
00232 void KisCanvas2::createQPainterCanvas()
00233 {
00234 #ifdef HAVE_OPENGL
00235 m_d->openGLImageTextures = 0;
00236 #endif
00237 m_d->currentCanvasIsOpenGL = false;
00238
00239 KisQPainterCanvas * canvasWidget = new KisQPainterCanvas(this, m_d->view);
00240 m_d->prescaledProjection = new KisPrescaledProjection();
00241 m_d->prescaledProjection->setViewConverter(m_d->viewConverter);
00242 m_d->prescaledProjection->setMonitorProfile(monitorProfile());
00243 canvasWidget->setPrescaledProjection(m_d->prescaledProjection);
00244
00245 connect(canvasWidget, SIGNAL(documentOriginChanged(const QPoint&)), this, SLOT(updateRulers()));
00246
00247 setCanvasWidget(canvasWidget);
00248 }
00249
00250 void KisCanvas2::createOpenGLCanvas()
00251 {
00252 #ifdef HAVE_OPENGL
00253 if (QGLFormat::hasOpenGL()) {
00254
00255 m_d->openGLImageTextures = KisOpenGLImageTextures::getImageTextures(m_d->view->image(), m_d->monitorProfile);
00256 KisOpenGLCanvas2 * canvasWidget = new KisOpenGLCanvas2(this, m_d->view, m_d->openGLImageTextures);
00257 setCanvasWidget(canvasWidget);
00258 m_d->currentCanvasIsOpenGL = true;
00259 m_d->currentCanvasUsesOpenGLShaders = m_d->openGLImageTextures->usingHDRExposureProgram();
00260
00261 connect(canvasWidget, SIGNAL(documentOriginChanged(const QPoint&)), this, SLOT(updateRulers()));
00262
00263 } else {
00264 warnKrita << "Tried to create OpenGL widget when system doesn't have OpenGL\n";
00265 createQPainterCanvas();
00266 }
00267 #endif
00268 }
00269
00270 void KisCanvas2::createCanvas()
00271 {
00272 KisConfig cfg;
00273 slotSetDisplayProfile(KoColorSpaceRegistry::instance()->profileByName(cfg.monitorProfile()));
00274
00275 if (cfg.useOpenGL()) {
00276 #ifdef HAVE_OPENGL
00277 createOpenGLCanvas();
00278 #else
00279 warnKrita << "OpenGL requested while its not available, starting qpainter canvas";
00280 createQPainterCanvas();
00281 #endif
00282 } else {
00283 createQPainterCanvas();
00284
00285 }
00286
00287 }
00288
00289 KisView2* KisCanvas2::view()
00290 {
00291 return m_d->view;
00292 }
00293
00294
00295 QRect KisCanvas2::viewRectFromDoc(const QRectF & rc)
00296 {
00297 QRect viewRect = m_d->viewConverter->documentToView(rc).toAlignedRect();
00298 viewRect = viewRect.translated(-m_d->documentOffset);
00299
00300
00301 viewRect.translate(documentOrigin());
00302 return viewRect;
00303 }
00304
00305
00306 void KisCanvas2::updateCanvasProjection(const QRect & rc)
00307 {
00308 if (m_d->prescaledProjection) {
00309 QRect vRect = m_d->prescaledProjection->updateCanvasProjection(rc);
00310 if (!vRect.isEmpty()) {
00311 vRect.translate(m_d->canvasWidget->documentOrigin());
00312 m_d->canvasWidget->widget()->update(vRect);
00313
00314 }
00315 }
00316 }
00317
00318
00319 void KisCanvas2::updateCanvas()
00320 {
00321 m_d->canvasWidget->widget()->update();
00322 }
00323
00324
00325 KisImageWSP KisCanvas2::image()
00326 {
00327 return m_d->view->image();
00328
00329 }
00330
00331 KoColorProfile * KisCanvas2::monitorProfile()
00332 {
00333 return m_d->monitorProfile;
00334 }
00335
00336 KisImageWSP KisCanvas2::currentImage()
00337 {
00338 return m_d->view->image();
00339 }
00340
00341 void KisCanvas2::setImageSize(qint32 w, qint32 h)
00342 {
00343 if (m_d->prescaledProjection)
00344 m_d->prescaledProjection->setImageSize(w, h);
00345 }
00346
00347 void KisCanvas2::connectCurrentImage()
00348 {
00349 #ifdef HAVE_OPENGL
00350 if (m_d->openGLImageTextures) {
00351 connect(m_d->openGLImageTextures, SIGNAL(sigImageUpdated(const QRect &)), SLOT(updateCanvas()));
00352 connect(m_d->openGLImageTextures, SIGNAL(sigSizeChanged(qint32, qint32)), SLOT(setImageSize(qint32, qint32)));
00353 } else {
00354 #endif
00355 connect(m_d->view->image(), SIGNAL(sigImageUpdated(const QRect &)), SLOT(updateCanvasProjection(const QRect &)));
00356 connect(m_d->view->image(), SIGNAL(sigSizeChanged(qint32, qint32)), SLOT(setImageSize(qint32, qint32)));
00357
00358 if (m_d->prescaledProjection) {
00359 m_d->prescaledProjection->setImage(m_d->view->image());
00360 }
00361
00362 #ifdef HAVE_OPENGL
00363 }
00364 #endif
00365 emit imageChanged(m_d->view->image());
00366 }
00367
00368 void KisCanvas2::disconnectCurrentImage()
00369 {
00370 #ifdef HAVE_OPENGL
00371 if (m_d->openGLImageTextures) {
00372 m_d->openGLImageTextures->disconnect(this);
00373 }
00374 #endif
00375 m_d->view->image()->disconnect(this);
00376 }
00377
00378 void KisCanvas2::resetCanvas()
00379 {
00380 KisConfig cfg;
00381 #if HAVE_OPENGL
00382
00383 if ((cfg.useOpenGL() != m_d->currentCanvasIsOpenGL) ||
00384 (m_d->currentCanvasIsOpenGL && (cfg.useOpenGLShaders() != m_d->currentCanvasUsesOpenGLShaders))) {
00385
00386 disconnectCurrentImage();
00387 createCanvas();
00388 connectCurrentImage();
00389 }
00390
00391 if (cfg.useOpenGL()) {
00392 m_d->openGLImageTextures->setMonitorProfile(monitorProfile());
00393 } else {
00394 if (image()) {
00395 updateCanvasProjection(image()->bounds());
00396 }
00397 }
00398 #endif
00399 m_d->canvasWidget->widget()->update();
00400 }
00401
00402 void KisCanvas2::documentOffsetMoved(const QPoint &documentOffset)
00403 {
00404 m_d->documentOffset = documentOffset;
00405 m_d->canvasWidget->documentOffsetMoved(documentOffset);
00406 }
00407
00408 void KisCanvas2::preScale()
00409 {
00410 if (!m_d->currentCanvasIsOpenGL && m_d->prescaledProjection)
00411 m_d->prescaledProjection->preScale();
00412 }
00413
00414 bool KisCanvas2::usingHDRExposureProgram()
00415 {
00416 #ifdef HAVE_OPENGL
00417 if (m_d->currentCanvasIsOpenGL) {
00418 if (m_d->openGLImageTextures->usingHDRExposureProgram()) {
00419 return true;
00420 }
00421 }
00422 #endif
00423 return false;
00424 }
00425
00426 void KisCanvas2::slotConfigChanged()
00427 {
00428 resetCanvas();
00429 }
00430
00431 void KisCanvas2::slotSetDisplayProfile(const KoColorProfile * profile)
00432 {
00433 m_d->monitorProfile = const_cast<KoColorProfile*>(profile);
00434 }
00435
00436 void KisCanvas2::addDecoration(KisCanvasDecoration* deco)
00437 {
00438 m_d->canvasWidget->addDecoration(deco);
00439 }
00440
00441 KisCanvasDecoration* KisCanvas2::decoration(const QString& id)
00442 {
00443 return m_d->canvasWidget->decoration(id);
00444 }
00445
00446
00447 QPoint KisCanvas2::documentOrigin() const
00448 {
00449 return m_d->canvasWidget->documentOrigin();
00450 }
00451
00452
00453 void KisCanvas2::adjustOrigin()
00454 {
00455 m_d->canvasWidget->adjustOrigin();
00456 }
00457
00458
00459 void KisCanvas2::updateRulers()
00460 {
00461 emit documentOriginChanged();
00462 }
00463
00464
00465 QPoint KisCanvas2::documentOffset() const
00466 {
00467 return m_d->documentOffset;
00468 }
00469
00470
00471 #include "kis_canvas2.moc"