/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiWord * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ #include "fv_ViewDoubleBuffering.h" #include "xap_App.h" #include "gr_Graphics.h" #include "gr_Painter.h" #include "fv_View.h" #include "ut_types.h" #include "ut_misc.h" #include "ut_debugmsg.h" //#define DEACTIVATE_FV_VIEW_DOUBLE_BUFFERING FV_ViewDoubleBuffering::FV_ViewDoubleBuffering(FV_View *pView, bool suspendDirectDrawing, bool callDrawOnlyAtTheEnd) : m_pView(pView), m_bCallDrawOnlyAtTheEnd(callDrawOnlyAtTheEnd), m_bSuspendDirectDrawing(suspendDirectDrawing) { this->initMostExtArgs(); } FV_ViewDoubleBuffering::~FV_ViewDoubleBuffering() { this->endDoubleBuffering(); } void FV_ViewDoubleBuffering::beginDoubleBuffering() { #ifdef DEACTIVATE_FV_VIEW_DOUBLE_BUFFERING return; #endif // MIQ: in abicommand the gui is likely not shown anyway // I also noticed some segvs when no-gui && dbuffer if( XAP_App::getApp()->getDisableDoubleBuffering() ) return; if(m_bSuspendDirectDrawing == true && m_bCallDrawOnlyAtTheEnd == false) { // You put me in a curious sitution: you want me to disable drawing between // beginDoubleBuffering and endDoubleBuffering, but you also want to draw // through _draw. At the moment, we cannot do that. UT_ASSERT(UT_NOT_IMPLEMENTED); } if(!m_pView->registerDoubleBufferingObject(this)) return; // We will need to direct calls through a painter since it may initialize // the device context on some platforms m_pPainter = new GR_Painter(m_pView->getGraphics()); m_pPainter->beginDoubleBuffering(); if(m_bSuspendDirectDrawing) m_pPainter->suspendDrawing(); } void FV_ViewDoubleBuffering::endDoubleBuffering() { #ifdef DEACTIVATE_FV_VIEW_DOUBLE_BUFFERING return; #endif if( XAP_App::getApp()->getDisableDoubleBuffering() ) return; if(!m_pView->unregisterDoubleBufferingObject(this)) return; if(m_bSuspendDirectDrawing) m_pPainter->resumeDrawing(); m_pPainter->endDoubleBuffering(); delete m_pPainter; if(m_bCallDrawOnlyAtTheEnd) this->callUnifiedDraw(); } void FV_ViewDoubleBuffering::recordViewDrawCall( UT_sint32 x, UT_sint32 y, UT_sint32 width, UT_sint32 height, bool bDirtyRunsOnly, bool /*bClip*/) { UT_Rect thisCallRect(x, y, width, height); const UT_Rect *clipRectFromGraphics = m_pView->getGraphics()->getClipRect(); // record actual _draw arguments this->extendDrawArgsIfNeccessary(&thisCallRect, clipRectFromGraphics, bDirtyRunsOnly); } bool FV_ViewDoubleBuffering::getCallDrawOnlyAtTheEnd() { return m_bCallDrawOnlyAtTheEnd; } void FV_ViewDoubleBuffering::callUnifiedDraw() { if(noRecordedDrawCalls()) return; m_pView->getGraphics()->setClipRect(&mostExtArgs.clipRect); m_pView->_draw( mostExtArgs.fullRect.left, mostExtArgs.fullRect.top, mostExtArgs.fullRect.width, mostExtArgs.fullRect.height, mostExtArgs.bDirtyRunsOnly, false); m_pView->getGraphics()->setClipRect(NULL); UT_DEBUGMSG(("ASFRENT: unified _draw call for a total of %d previous calls.\n", mostExtArgs.callCount)); } bool FV_ViewDoubleBuffering::noRecordedDrawCalls() { return mostExtArgs.callCount == 0; } void FV_ViewDoubleBuffering::redrawEntireScreen() { this->m_pView->_draw( 0, 0, m_pView->getWindowWidth(), m_pView->getWindowHeight(), false, false); } void FV_ViewDoubleBuffering::initMostExtArgs() { mostExtArgs.callCount = 0; } void FV_ViewDoubleBuffering::extendDrawArgsIfNeccessary( UT_Rect *thisCallRect, const UT_Rect *clipRectFromGraphics, bool bDirtyRunsOnly) { if(clipRectFromGraphics == NULL) clipRectFromGraphics = thisCallRect; if(mostExtArgs.callCount == 0) { // then this is a first call, just record parameters mostExtArgs.bDirtyRunsOnly = bDirtyRunsOnly; mostExtArgs.fullRect = *thisCallRect; mostExtArgs.clipRect = *clipRectFromGraphics; } else { // extend those args // 1. dirty runs: false means more if(bDirtyRunsOnly == false) mostExtArgs.bDirtyRunsOnly = false; // 2. full rectangle mostExtArgs.fullRect.unionRect(thisCallRect); // 3. clip rectangle mostExtArgs.clipRect.unionRect(clipRectFromGraphics); } mostExtArgs.callCount++; }