Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members

DoubleBufferCanvas.h

Go to the documentation of this file.
00001 /*********************************************************************************
00002  *
00003  * Razor! Engine - A modular C++ presentation engine
00004  *
00005  * $Id$
00006  *
00007  * Copyright (c) 2000 Tilo Christ. All Rights Reserved.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  **********************************************************************************/
00024 
00025 
00026 #ifndef DOUBLEBUFFERCANVAS_H
00027 #define DOUBLEBUFFERCANVAS_H
00028 
00029 #include <PalmOS.h>
00030 #include "Device.h"
00031 #include "Canvas.h"
00032 #include "Customization.h"
00033 
00034 
00035 
00036 /**
00037  * DoubleBufferCanvas manages a <EM>double-buffered</EM> canvas into which a user can paint.
00038  */
00039 class DoubleBufferCanvas : public Canvas
00040 {
00041     public:
00042 
00043     DoubleBufferCanvas() : Canvas()
00044     {
00045         {
00046             Err error;
00047             // Check whether current depth is already sufficient...
00048             UInt32 currentDepth;
00049             WinScreenMode(winScreenModeGet, NULL, NULL, &currentDepth, NULL);
00050 
00051             if (currentDepth < canvasRequiredDepth)
00052             {               
00053                 // Set the screen to the desired depth
00054                 error = WinScreenMode(winScreenModeSet, NULL, NULL, &canvasRequiredDepth, NULL);
00055                 if (error)
00056                     Device::panic(error, "Unable to set screen mode!");
00057             }
00058             
00059             // Ugly hack against broken PalmOS 3.1. This is fixed in 3.1.1
00060             if (canvasRequiredDepth == 2)
00061             {
00062                 if ((Device::supports31) && (!(Device::supports35)))
00063                 {                   
00064                     UInt16 value = 3 + (7 << 4) + (1 << 12);
00065                     *((UInt16 *)0xFFFFFA32) = value;
00066                 }
00067             }
00068         }
00069 
00070 
00071         // Remember old draw window
00072         WinHandle oldDrawWinH = WinGetDrawWindow();
00073 
00074         // Setup the screenBuffer.
00075         UInt16 error;
00076         screenBufferH = WinCreateOffscreenWindow(getWidth(), getHeight(), screenFormat, &error);
00077         if (error)
00078             Device::panic(error, "Cannot create double buffer.");
00079                 
00080         // Clear buffer for use
00081         WinSetDrawWindow(screenBufferH);
00082         WinEraseRectangle(&displayBounds, 0);
00083 
00084         // Restore old draw window
00085         WinSetDrawWindow(oldDrawWinH);          
00086 
00087         // Prepare bounds for screen copy
00088         currentBounds.topLeft.x = 0;
00089         currentBounds.topLeft.y = 0;
00090         currentBounds.extent.x = getWidth();
00091         currentBounds.extent.y = getHeight();
00092     }
00093     
00094     
00095     ~DoubleBufferCanvas()
00096     {
00097         // Destroy the double buffered window
00098         WinDeleteWindow(screenBufferH, false);
00099 
00100         // Restore display color-depth to normal
00101         WinScreenMode(winScreenModeSetToDefaults, NULL, NULL, NULL, NULL);
00102     }
00103 
00104     
00105     void beginDraw(WinLockInitType initMode)
00106     {
00107         deviceDrawWindowH = WinGetDrawWindow();
00108         WinSetDrawWindow(screenBufferH);    
00109 
00110 
00111         lastBounds.topLeft.x = currentBounds.topLeft.x;
00112         lastBounds.topLeft.y = currentBounds.topLeft.y;
00113         lastBounds.extent.x = currentBounds.extent.x;
00114         lastBounds.extent.y = currentBounds.extent.y;
00115 
00116 
00117         switch(initMode)
00118         {
00119             case winLockCopy:
00120             case winLockDontCare:
00121                 break;
00122 
00123             case winLockErase:
00124                 // Clear buffer for use
00125                 WinEraseRectangle(&displayBounds, 0);
00126                 
00127                 break;
00128             default:
00129                 ErrNonFatalDisplay("DoubleBufferCanvas.beginDraw: Invalid initMode");
00130                 break;
00131         }
00132     }
00133     
00134     
00135     void endDraw(RectangleType *bounds)
00136     {
00137         ErrNonFatalDisplayIf(bounds == NULL, "DoubleBufferCanvas.endDraw: bounds == NULL");
00138 
00139         WinSetDrawWindow(deviceDrawWindowH);
00140         
00141         currentBounds.topLeft.x = bounds->topLeft.x;
00142         currentBounds.topLeft.y = bounds->topLeft.y;
00143         currentBounds.extent.x = bounds->extent.x;
00144         currentBounds.extent.y = bounds->extent.y;
00145 
00146         Canvas::uniteBounds(&lastBounds, &currentBounds, &copyBounds);
00147 
00148         // Don't show stuff off screen
00149         copyBounds.topLeft.x = max(copyBounds.topLeft.x, 0);
00150         copyBounds.topLeft.y = max(copyBounds.topLeft.y, 0);
00151 
00152         copyBounds.extent.x = min(copyBounds.extent.x, getWidth() - copyBounds.topLeft.x);
00153         copyBounds.extent.y = min(copyBounds.extent.y, getHeight() - copyBounds.topLeft.y);
00154 
00155         // Align the x coordinate with the nearest word to speed up the WinCopyRectangle.
00156         UInt16 offset = copyBounds.topLeft.x & 0x000F;
00157         if (offset)
00158         {
00159             copyBounds.topLeft.x -= offset;
00160             copyBounds.extent.x += offset;
00161         }
00162     
00163         // Push the extent out to fill the entire word.
00164         copyBounds.extent.x = (copyBounds.extent.x + 0x0F) & 0xFFF0;
00165     }
00166 
00167 
00168     void show()
00169     {
00170         // Copy the screenBuffer
00171         WinCopyRectangle (screenBufferH, 0, &copyBounds, 
00172             copyBounds.topLeft.x, 
00173             copyBounds.topLeft.y, 
00174             winPaint); 
00175     }
00176 
00177 
00178     private:
00179     WinHandle deviceDrawWindowH;
00180     WinHandle screenBufferH;
00181 
00182     RectangleType currentBounds;
00183     RectangleType lastBounds;
00184     RectangleType copyBounds;
00185 };
00186 
00187 
00188 #endif

Razor! Engine Developer's Guide. Copyright © by Tilo Christ. All Rights Reserved. Last updated: 4 Nov 2000