00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 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 00038
00039 class DoubleBufferCanvas : public Canvas
00040 {
00041 public:
00042
00043 DoubleBufferCanvas() : Canvas()
00044 {
00045 {
00046 Err error;
00047
00048 UInt32 currentDepth;
00049 WinScreenMode(winScreenModeGet, NULL, NULL, ¤tDepth, NULL);
00050
00051 if (currentDepth < canvasRequiredDepth)
00052 {
00053
00054 error = WinScreenMode(winScreenModeSet, NULL, NULL, &canvasRequiredDepth, NULL);
00055 if (error)
00056 Device::panic(error, "Unable to set screen mode!");
00057 }
00058
00059
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
00072 WinHandle oldDrawWinH = WinGetDrawWindow();
00073
00074
00075 UInt16 error;
00076 screenBufferH = WinCreateOffscreenWindow(getWidth(), getHeight(), screenFormat, &error);
00077 if (error)
00078 Device::panic(error, "Cannot create double buffer.");
00079
00080
00081 WinSetDrawWindow(screenBufferH);
00082 WinEraseRectangle(&displayBounds, 0);
00083
00084
00085 WinSetDrawWindow(oldDrawWinH);
00086
00087
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
00098 WinDeleteWindow(screenBufferH, false);
00099
00100
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
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, ¤tBounds, ©Bounds);
00147
00148
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
00156 UInt16 offset = copyBounds.topLeft.x & 0x000F;
00157 if (offset)
00158 {
00159 copyBounds.topLeft.x -= offset;
00160 copyBounds.extent.x += offset;
00161 }
00162
00163
00164 copyBounds.extent.x = (copyBounds.extent.x + 0x0F) & 0xFFF0;
00165 }
00166
00167
00168 void show()
00169 {
00170
00171 WinCopyRectangle (screenBufferH, 0, ©Bounds,
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