Lots of image/bitmap processing updates.
[wxWidgets.git] / src / os2 / dcmemory.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dcmemory.cpp
3 // Purpose: wxMemoryDC class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/14/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/utils.h"
17 #include "wx/app.h"
18 #include "wx/log.h"
19 #endif
20
21 #include "wx/os2/private.h"
22
23 #include "wx/dcmemory.h"
24
25 IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC)
26
27 /////////////////////////////////////////////////////////////////////////////
28 // Memory DC
29 /////////////////////////////////////////////////////////////////////////////
30
31 wxMemoryDC::wxMemoryDC(void)
32 {
33 CreateCompatible(NULL);
34 Init();
35 } // end of wxMemoryDC::wxMemoryDC
36
37 wxMemoryDC::wxMemoryDC(
38 wxDC* pOldDC
39 )
40 {
41 pOldDC->BeginDrawing();
42 CreateCompatible(pOldDC);
43 pOldDC->EndDrawing();
44 Init();
45 } // end of wxMemoryDC::wxMemoryDC
46
47 void wxMemoryDC::Init()
48 {
49 if (m_ok)
50 {
51 SetBrush(*wxWHITE_BRUSH);
52 SetPen(*wxBLACK_PEN);
53
54 // the background mode is only used for text background and is set in
55 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT
56 ::GpiSetBackMix( GetHPS(), BM_LEAVEALONE );
57 }
58 memset(&m_vRclPaint, 0, sizeof(m_vRclPaint));
59 } // end of wxMemoryDC::Init
60
61 bool wxMemoryDC::CreateCompatible(
62 wxDC* pDC
63 )
64 {
65 HDC hDC;
66 HPS hPS;
67 DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
68 SIZEL vSize = {0, 0};
69
70 //
71 // Create a memory device context
72 //
73 hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
74 if (hDC != DEV_ERROR)
75 {
76 hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
77 if (hPS != GPI_ERROR)
78 {
79 m_hPS = hPS;
80 m_hDC = hDC;
81 m_ok = TRUE;
82 m_bOwnsDC = TRUE;
83 //
84 // Set the wxWindows color table
85 //
86 ::GpiCreateLogColorTable( m_hPS
87 ,0L
88 ,LCOLF_CONSECRGB
89 ,0L
90 ,(LONG)wxTheColourDatabase->m_nSize
91 ,(PLONG)wxTheColourDatabase->m_palTable
92 );
93 ::GpiCreateLogColorTable( m_hPS
94 ,0L
95 ,LCOLF_RGB
96 ,0L
97 ,0L
98 ,NULL
99 );
100 }
101 else
102 {
103 m_hPS = NULLHANDLE;
104 m_hDC = NULLHANDLE;
105 m_ok = FALSE;
106 m_bOwnsDC = FALSE;
107 }
108 }
109 else
110 {
111 m_hPS = NULLHANDLE;
112 m_hDC = NULLHANDLE;
113 m_ok = FALSE;
114 m_bOwnsDC = FALSE;
115 }
116
117 //
118 // As we created the DC, we must delete it in the dtor
119 //
120 m_bOwnsDC = TRUE;
121 m_ok = m_hDC != 0;
122 return m_ok;
123 } // end of wxMemoryDC::CreateCompatible
124
125 void wxMemoryDC::SelectObject(
126 const wxBitmap& rBitmap
127 )
128 {
129 //
130 // Select old bitmap out of the device context
131 //
132 if (m_hOldBitmap)
133 {
134 ::GpiSetBitmap(m_hPS, NULLHANDLE);
135 if (m_vSelectedBitmap.Ok())
136 {
137 m_vSelectedBitmap.SetSelectedInto(NULL);
138 m_vSelectedBitmap = wxNullBitmap;
139 }
140 }
141
142 //
143 // Check for whether the bitmap is already selected into a device context
144 //
145 wxCHECK_RET( !rBitmap.GetSelectedInto() ||
146 (rBitmap.GetSelectedInto() == this),
147 wxT("Bitmap is selected in another wxMemoryDC, delete the first wxMemoryDC or use SelectObject(NULL)") );
148
149 m_vSelectedBitmap = rBitmap;
150
151 WXHBITMAP hBmp = rBitmap.GetHBITMAP();
152
153 if (!hBmp)
154 return;
155
156 m_vSelectedBitmap.SetSelectedInto(this);
157 hBmp = (WXHBITMAP)::GpiSetBitmap(m_hPS, (HBITMAP)hBmp);
158
159 if (hBmp == HBM_ERROR)
160 {
161 wxLogLastError(wxT("SelectObject(memDC, bitmap)"));
162 wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC"));
163 }
164 else if (!m_hOldBitmap)
165 {
166 m_hOldBitmap = hBmp;
167 }
168 } // end of wxMemoryDC::SelectObject
169
170 void wxMemoryDC::DoGetSize(
171 int* pWidth
172 , int* pHeight
173 ) const
174 {
175 if (!m_vSelectedBitmap.Ok())
176 {
177 *pWidth = 0;
178 *pHeight = 0;
179 return;
180 }
181 *pWidth = m_vSelectedBitmap.GetWidth();
182 *pHeight = m_vSelectedBitmap.GetHeight();
183 } // end of wxMemoryDC::DoGetSize
184
185 void wxMemoryDC::DoDrawRectangle(
186 wxCoord vX
187 , wxCoord vY
188 , wxCoord vWidth
189 , wxCoord vHeight
190 )
191 {
192 wxDC::DoDrawRectangle(vX, vY, vWidth, vHeight);
193
194 //
195 // Debug testing:
196 //
197 if (m_vSelectedBitmap.GetHBITMAP() != NULLHANDLE)
198 {
199 BITMAPINFOHEADER2 vHeader;
200 BITMAPINFO2 vInfo;
201
202 vHeader.cbFix = 16L;
203 if (::GpiQueryBitmapInfoHeader(m_vSelectedBitmap.GetHBITMAP(), &vHeader))
204 {
205 unsigned char* pucData = NULL;
206 unsigned char* pucBits;
207 int nBytesPerLine = m_vSelectedBitmap.GetWidth() * 3;
208 LONG lScans = 0L;
209 POINTL vPoint;
210 LONG lColor;
211 LONG alFormats[24]; // Max formats OS/2 PM supports
212 ULONG ulBitcount;
213
214 ::GpiQueryDeviceBitmapFormats(m_hPS, 24, alFormats);
215 ulBitcount = alFormats[1]; // the best one for the device
216 if (ulBitcount > 24)
217 ulBitcount = 24; // MAX bits supported by PM
218 vInfo.cbFix = 16;
219 vInfo.cx = vHeader.cx;
220 vInfo.cy = vHeader.cy;
221 vInfo.cPlanes = vHeader.cPlanes;
222 vInfo.cBitCount = ulBitcount;
223 pucData = (unsigned char*)malloc(nBytesPerLine * m_vSelectedBitmap.GetHeight());
224 if ((lScans = ::GpiQueryBitmapBits( m_hPS
225 ,0L
226 ,(LONG)m_vSelectedBitmap.GetHeight()
227 ,(PBYTE)pucData
228 ,&vInfo
229 )) == GPI_ALTERROR)
230 {
231 ERRORID vError;
232 wxString sError;
233
234 vError = ::WinGetLastError(vHabmain);
235 sError = wxPMErrorToStr(vError);
236 }
237 pucBits = pucData;
238 for (int i = 0; i < m_vSelectedBitmap.GetHeight(); i++)
239 {
240 for (int j = 0; j < m_vSelectedBitmap.GetWidth(); j++)
241 {
242 vPoint.x = j; vPoint.y = i;
243 lColor = ::GpiQueryPel(m_hPS, &vPoint);
244 *(pucBits++) = (unsigned char)lColor;
245 *(pucBits++) = (unsigned char)(lColor >> 8);
246 *(pucBits++) = (unsigned char)(lColor >> 16);
247 }
248 }
249 if ((lScans = ::GpiSetBitmapBits( m_hPS
250 ,0
251 ,(LONG)m_vSelectedBitmap.GetHeight()
252 ,(PBYTE)pucData
253 ,&vInfo
254 )) == GPI_ALTERROR)
255 {
256 ERRORID vError;
257 wxString sError;
258
259 vError = ::WinGetLastError(vHabmain);
260 sError = wxPMErrorToStr(vError);
261 }
262 free(pucData);
263 }
264 }
265 } // end of wxMemoryDC::DoDrawRectangle
266
267 void wxMemoryDC::DoDrawRoundedRectangle(
268 wxCoord vX
269 , wxCoord vY
270 , wxCoord vWidth
271 , wxCoord vHeight
272 , double dRadius
273 )
274 {
275 wxDC::DoDrawRoundedRectangle(vX, vY, vWidth, vHeight, dRadius);
276
277 //
278 // Debug testing:
279 //
280 if (m_vSelectedBitmap.GetHBITMAP() != NULLHANDLE)
281 {
282 BITMAPINFOHEADER2 vHeader;
283 BITMAPINFO2 vInfo;
284
285 vHeader.cbFix = 16L;
286 if (::GpiQueryBitmapInfoHeader(m_vSelectedBitmap.GetHBITMAP(), &vHeader))
287 {
288 unsigned char* pucData = NULL;
289 unsigned char* pucBits;
290 int nBytesPerLine = m_vSelectedBitmap.GetWidth() * 3;
291 LONG lScans = 0L;
292 POINTL vPoint;
293 LONG lColor;
294 LONG alFormats[24]; // Max formats OS/2 PM supports
295 ULONG ulBitcount;
296
297 ::GpiQueryDeviceBitmapFormats(m_hPS, 24, alFormats);
298 ulBitcount = alFormats[1]; // the best one for the device
299 if (ulBitcount > 24)
300 ulBitcount = 24; // MAX bits supported by PM
301 vInfo.cbFix = 16;
302 vInfo.cx = vHeader.cx;
303 vInfo.cy = vHeader.cy;
304 vInfo.cPlanes = vHeader.cPlanes;
305 vInfo.cBitCount = ulBitcount;
306 pucData = (unsigned char*)malloc(nBytesPerLine * m_vSelectedBitmap.GetHeight());
307 if ((lScans = ::GpiQueryBitmapBits( m_hPS
308 ,0L
309 ,(LONG)m_vSelectedBitmap.GetHeight()
310 ,(PBYTE)pucData
311 ,&vInfo
312 )) == GPI_ALTERROR)
313 {
314 ERRORID vError;
315 wxString sError;
316
317 vError = ::WinGetLastError(vHabmain);
318 sError = wxPMErrorToStr(vError);
319 }
320 pucBits = pucData;
321 for (int i = 0; i < m_vSelectedBitmap.GetHeight(); i++)
322 {
323 for (int j = 0; j < m_vSelectedBitmap.GetWidth(); j++)
324 {
325 vPoint.x = j; vPoint.y = i;
326 lColor = ::GpiQueryPel(m_hPS, &vPoint);
327 *(pucBits++) = (unsigned char)lColor;
328 *(pucBits++) = (unsigned char)(lColor >> 8);
329 *(pucBits++) = (unsigned char)(lColor >> 16);
330 }
331 }
332 if ((lScans = ::GpiSetBitmapBits( m_hPS
333 ,0
334 ,(LONG)m_vSelectedBitmap.GetHeight()
335 ,(PBYTE)pucData
336 ,&vInfo
337 )) == GPI_ALTERROR)
338 {
339 ERRORID vError;
340 wxString sError;
341
342 vError = ::WinGetLastError(vHabmain);
343 sError = wxPMErrorToStr(vError);
344 }
345 free(pucData);
346 }
347 }
348 } // end of wxMemoryDC::DoDrawRectangle
349