More image 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 extern void wxLoadBitmapWithData( HPS hPS
28 ,HBITMAP hBitmap
29 ,int nWidth
30 ,int nHeight
31 );
32
33 /////////////////////////////////////////////////////////////////////////////
34 // Memory DC
35 /////////////////////////////////////////////////////////////////////////////
36
37 wxMemoryDC::wxMemoryDC(void)
38 {
39 CreateCompatible(NULL);
40 Init();
41 } // end of wxMemoryDC::wxMemoryDC
42
43 wxMemoryDC::wxMemoryDC(
44 wxDC* pOldDC
45 )
46 {
47 pOldDC->BeginDrawing();
48 CreateCompatible(pOldDC);
49 pOldDC->EndDrawing();
50 Init();
51 } // end of wxMemoryDC::wxMemoryDC
52
53 void wxMemoryDC::Init()
54 {
55 if (m_ok)
56 {
57 SetBrush(*wxWHITE_BRUSH);
58 SetPen(*wxBLACK_PEN);
59
60 // the background mode is only used for text background and is set in
61 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT
62 ::GpiSetBackMix( GetHPS(), BM_LEAVEALONE );
63 }
64 memset(&m_vRclPaint, 0, sizeof(m_vRclPaint));
65 } // end of wxMemoryDC::Init
66
67 bool wxMemoryDC::CreateCompatible(
68 wxDC* pDC
69 )
70 {
71 HDC hDC;
72 HPS hPS;
73 DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
74 SIZEL vSize = {0, 0};
75
76 //
77 // Create a memory device context
78 //
79 hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
80 if (hDC != DEV_ERROR)
81 {
82 hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
83 if (hPS != GPI_ERROR)
84 {
85 m_hPS = hPS;
86 m_hDC = hDC;
87 m_ok = TRUE;
88 m_bOwnsDC = TRUE;
89 //
90 // Set the wxWindows color table
91 //
92 ::GpiCreateLogColorTable( m_hPS
93 ,0L
94 ,LCOLF_CONSECRGB
95 ,0L
96 ,(LONG)wxTheColourDatabase->m_nSize
97 ,(PLONG)wxTheColourDatabase->m_palTable
98 );
99 ::GpiCreateLogColorTable( m_hPS
100 ,0L
101 ,LCOLF_RGB
102 ,0L
103 ,0L
104 ,NULL
105 );
106 }
107 else
108 {
109 m_hPS = NULLHANDLE;
110 m_hDC = NULLHANDLE;
111 m_ok = FALSE;
112 m_bOwnsDC = FALSE;
113 }
114 }
115 else
116 {
117 m_hPS = NULLHANDLE;
118 m_hDC = NULLHANDLE;
119 m_ok = FALSE;
120 m_bOwnsDC = FALSE;
121 }
122
123 //
124 // As we created the DC, we must delete it in the dtor
125 //
126 m_bOwnsDC = TRUE;
127 m_ok = m_hDC != 0;
128 return m_ok;
129 } // end of wxMemoryDC::CreateCompatible
130
131 void wxMemoryDC::SelectObject(
132 const wxBitmap& rBitmap
133 )
134 {
135 //
136 // Select old bitmap out of the device context
137 //
138 if (m_hOldBitmap)
139 {
140 ::GpiSetBitmap(m_hPS, NULLHANDLE);
141 if (m_vSelectedBitmap.Ok())
142 {
143 m_vSelectedBitmap.SetSelectedInto(NULL);
144 m_vSelectedBitmap = wxNullBitmap;
145 }
146 }
147
148 //
149 // Check for whether the bitmap is already selected into a device context
150 //
151 wxCHECK_RET( !rBitmap.GetSelectedInto() ||
152 (rBitmap.GetSelectedInto() == this),
153 wxT("Bitmap is selected in another wxMemoryDC, delete the first wxMemoryDC or use SelectObject(NULL)") );
154
155 m_vSelectedBitmap = rBitmap;
156
157 WXHBITMAP hBmp = rBitmap.GetHBITMAP();
158
159 if (!hBmp)
160 return;
161
162 m_vSelectedBitmap.SetSelectedInto(this);
163 hBmp = (WXHBITMAP)::GpiSetBitmap(m_hPS, (HBITMAP)hBmp);
164
165 if (hBmp == HBM_ERROR)
166 {
167 wxLogLastError(wxT("SelectObject(memDC, bitmap)"));
168 wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC"));
169 }
170 else if (!m_hOldBitmap)
171 {
172 m_hOldBitmap = hBmp;
173 }
174 } // end of wxMemoryDC::SelectObject
175
176 void wxMemoryDC::DoGetSize(
177 int* pWidth
178 , int* pHeight
179 ) const
180 {
181 if (!m_vSelectedBitmap.Ok())
182 {
183 *pWidth = 0;
184 *pHeight = 0;
185 return;
186 }
187 *pWidth = m_vSelectedBitmap.GetWidth();
188 *pHeight = m_vSelectedBitmap.GetHeight();
189 } // end of wxMemoryDC::DoGetSize
190
191 void wxMemoryDC::DoDrawRectangle(
192 wxCoord vX
193 , wxCoord vY
194 , wxCoord vWidth
195 , wxCoord vHeight
196 )
197 {
198 wxDC::DoDrawRectangle(vX, vY, vWidth, vHeight);
199
200 wxLoadBitmapWithData( m_hPS
201 ,(HBITMAP)m_vSelectedBitmap.GetHBITMAP()
202 ,m_vSelectedBitmap.GetWidth()
203 ,m_vSelectedBitmap.GetHeight()
204 );
205 } // end of wxMemoryDC::DoDrawRectangle
206
207 void wxMemoryDC::DoDrawRoundedRectangle(
208 wxCoord vX
209 , wxCoord vY
210 , wxCoord vWidth
211 , wxCoord vHeight
212 , double dRadius
213 )
214 {
215 wxDC::DoDrawRoundedRectangle(vX, vY, vWidth, vHeight, dRadius);
216
217 wxLoadBitmapWithData( m_hPS
218 ,(HBITMAP)m_vSelectedBitmap.GetHBITMAP()
219 ,m_vSelectedBitmap.GetWidth()
220 ,m_vSelectedBitmap.GetHeight()
221 );
222 } // end of wxMemoryDC::DoDrawRoundedRectangle
223
224 void wxMemoryDC::DoDrawText(
225 const wxString& rsText
226 , wxCoord vX
227 , wxCoord vY
228 )
229 {
230 wxDC::DoDrawText(rsText, vX, vY);
231
232 wxLoadBitmapWithData( m_hPS
233 ,(HBITMAP)m_vSelectedBitmap.GetHBITMAP()
234 ,m_vSelectedBitmap.GetWidth()
235 ,m_vSelectedBitmap.GetHeight()
236 );
237 } // end of wxMemoryDC::DoDrawRectangle
238
239 void wxMemoryDC::DoDrawLine(
240 wxCoord vX1
241 , wxCoord vY1
242 , wxCoord vX2
243 , wxCoord vY2
244 )
245 {
246 wxDC::DoDrawLine(vX1, vY1, vX2, vY2);
247
248 wxLoadBitmapWithData( m_hPS
249 ,(HBITMAP)m_vSelectedBitmap.GetHBITMAP()
250 ,m_vSelectedBitmap.GetWidth()
251 ,m_vSelectedBitmap.GetHeight()
252 );
253 } // end of wxMemoryDC::DoDrawRoundedRectangle
254
255 void wxLoadBitmapWithData(
256 HPS hPS
257 , HBITMAP hBitmap
258 , int nWidth
259 , int nHeight
260 )
261 {
262 BITMAPINFOHEADER2 vHeader;
263 BITMAPINFO2 vInfo;
264
265 vHeader.cbFix = 16L;
266 if (::GpiQueryBitmapInfoHeader(hBitmap, &vHeader))
267 {
268 unsigned char* pucData = NULL;
269 unsigned char* pucBits;
270 int nBytesPerLine = nWidth * 3;
271 LONG lScans = 0L;
272 POINTL vPoint;
273 LONG lColor;
274
275 vInfo.cbFix = 16;
276 vInfo.cx = vHeader.cx;
277 vInfo.cy = vHeader.cy;
278 vInfo.cPlanes = vHeader.cPlanes;
279 vInfo.cBitCount = 24;
280 pucData = (unsigned char*)malloc(nBytesPerLine * nHeight);
281 pucBits = pucData;
282 for (int i = 0; i < nHeight; i++)
283 {
284 for (int j = 0; j < nWidth; j++)
285 {
286 vPoint.x = j; vPoint.y = i;
287 lColor = ::GpiQueryPel(hPS, &vPoint);
288 *(pucBits++) = (unsigned char)lColor;
289 *(pucBits++) = (unsigned char)(lColor >> 8);
290 *(pucBits++) = (unsigned char)(lColor >> 16);
291 }
292 }
293 if ((lScans = ::GpiSetBitmapBits( hPS
294 ,0
295 ,(LONG)nHeight
296 ,(PBYTE)pucData
297 ,&vInfo
298 )) == GPI_ALTERROR)
299 {
300 ERRORID vError;
301 wxString sError;
302
303 vError = ::WinGetLastError(vHabmain);
304 sError = wxPMErrorToStr(vError);
305 }
306 free(pucData);
307 }
308 }