Added some tentative wxMotif clipboard code; did some file formatting
[wxWidgets.git] / src / motif / dc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dc.cpp
3 // Purpose: wxDC class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dc.h"
14 #endif
15
16 #include "wx/dc.h"
17 #include "wx/dcmemory.h"
18
19 #if !USE_SHARED_LIBRARY
20 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
21 #endif
22
23 //-----------------------------------------------------------------------------
24 // constants
25 //-----------------------------------------------------------------------------
26
27 #define mm2inches 0.0393700787402
28 #define inches2mm 25.4
29 #define mm2twips 56.6929133859
30 #define twips2mm 0.0176388888889
31 #define mm2pt 2.83464566929
32 #define pt2mm 0.352777777778
33
34 //-----------------------------------------------------------------------------
35 // wxDC
36 //-----------------------------------------------------------------------------
37
38 wxDC::wxDC(void)
39 {
40 m_ok = FALSE;
41 m_optimize = FALSE;
42 m_colour = TRUE;
43 m_clipping = FALSE;
44
45 m_mm_to_pix_x = 1.0;
46 m_mm_to_pix_y = 1.0;
47
48 m_logicalOriginX = 0;
49 m_logicalOriginY = 0;
50 m_deviceOriginX = 0;
51 m_deviceOriginY = 0;
52 m_internalDeviceOriginX = 0;
53 m_internalDeviceOriginY = 0;
54 m_externalDeviceOriginX = 0;
55 m_externalDeviceOriginY = 0;
56
57 m_logicalScaleX = 1.0;
58 m_logicalScaleY = 1.0;
59 m_userScaleX = 1.0;
60 m_userScaleY = 1.0;
61 m_scaleX = 1.0;
62 m_scaleY = 1.0;
63
64 m_mappingMode = MM_TEXT;
65 m_needComputeScaleX = FALSE;
66 m_needComputeScaleY = FALSE;
67
68 m_signX = 1; // default x-axis left to right
69 m_signY = 1; // default y-axis top down
70
71 m_maxX = m_maxY = -100000;
72 m_minY = m_minY = 100000;
73
74 m_logicalFunction = wxCOPY;
75 // m_textAlignment = wxALIGN_TOP_LEFT;
76 m_backgroundMode = wxTRANSPARENT;
77
78 m_textForegroundColour = *wxBLACK;
79 m_textBackgroundColour = *wxWHITE;
80 m_pen = *wxBLACK_PEN;
81 m_font = *wxNORMAL_FONT;
82 m_brush = *wxTRANSPARENT_BRUSH;
83 m_backgroundBrush = *wxWHITE_BRUSH;
84
85 m_isInteractive = FALSE;
86
87 // m_palette = wxAPP_COLOURMAP;
88 };
89
90 wxDC::~wxDC(void)
91 {
92 };
93
94 void wxDC::DrawIcon( const wxIcon &WXUNUSED(icon), long WXUNUSED(x), long WXUNUSED(y))
95 {
96 };
97
98 void wxDC::DrawBitmap( const wxBitmap& bitmap, long x, long y, bool useMask )
99 {
100 if (!bitmap.Ok())
101 return;
102
103 wxMemoryDC memDC;
104 memDC.SelectObject(bitmap);
105
106 /* Not sure if we need this. The mask should leave the
107 * masked areas as per the original background of this DC.
108 if (useMask)
109 {
110 // There might be transparent areas, so make these
111 // the same colour as this DC
112 memDC.SetBackground(* GetBackground());
113 memDC.Clear();
114 }
115 */
116
117 Blit(x, y, bitmap.GetWidth(), bitmap.GetHeight(), & memDC, 0, 0, wxCOPY, useMask);
118
119 memDC.SelectObject(wxNullBitmap);
120 };
121
122
123 void wxDC::DrawPoint( wxPoint& point )
124 {
125 DrawPoint( point.x, point.y );
126 };
127
128 void wxDC::DrawPolygon( wxList *list, long xoffset, long yoffset, int fillStyle )
129 {
130 int n = list->Number();
131 wxPoint *points = new wxPoint[n];
132
133 int i = 0;
134 for( wxNode *node = list->First(); node; node = node->Next() )
135 {
136 wxPoint *point = (wxPoint *)node->Data();
137 points[i].x = point->x;
138 points[i++].y = point->y;
139 };
140 DrawPolygon( n, points, xoffset, yoffset, fillStyle );
141 delete[] points;
142 };
143
144 void wxDC::DrawLines( wxList *list, long xoffset, long yoffset )
145 {
146 int n = list->Number();
147 wxPoint *points = new wxPoint[n];
148
149 int i = 0;
150 for( wxNode *node = list->First(); node; node = node->Next() )
151 {
152 wxPoint *point = (wxPoint *)node->Data();
153 points[i].x = point->x;
154 points[i++].y = point->y;
155 };
156 DrawLines( n, points, xoffset, yoffset );
157 delete []points;
158 };
159
160 void wxDC::DrawSpline( long x1, long y1, long x2, long y2, long x3, long y3 )
161 {
162 wxList list;
163 list.Append( (wxObject*)new wxPoint(x1, y1) );
164 list.Append( (wxObject*)new wxPoint(x2, y2) );
165 list.Append( (wxObject*)new wxPoint(x3, y3) );
166 DrawSpline(&list);
167 wxNode *node = list.First();
168 while (node)
169 {
170 wxPoint *p = (wxPoint*)node->Data();
171 delete p;
172 node = node->Next();
173 };
174 };
175
176 void wxDC::DrawSpline( int n, wxPoint points[] )
177 {
178 wxList list;
179 for (int i = 0; i < n; i++) list.Append( (wxObject*)&points[i] );
180 DrawSpline( &list );
181 };
182
183 void wxDC::SetClippingRegion( long x, long y, long width, long height )
184 {
185 m_clipping = TRUE;
186 m_clipX1 = x;
187 m_clipY1 = y;
188 m_clipX2 = x + width;
189 m_clipY2 = y + height;
190 };
191
192 void wxDC::DestroyClippingRegion(void)
193 {
194 m_clipping = FALSE;
195 };
196
197 void wxDC::GetClippingBox( long *x, long *y, long *width, long *height ) const
198 {
199 if (m_clipping)
200 {
201 if (x) *x = m_clipX1;
202 if (y) *y = m_clipY1;
203 if (width) *width = (m_clipX2 - m_clipX1);
204 if (height) *height = (m_clipY2 - m_clipY1);
205 }
206 else
207 *x = *y = *width = *height = 0;
208 };
209
210 void wxDC::GetSize( int* width, int* height ) const
211 {
212 *width = m_maxX-m_minX;
213 *height = m_maxY-m_minY;
214 };
215
216 void wxDC::GetSizeMM( long* width, long* height ) const
217 {
218 int w = 0;
219 int h = 0;
220 GetSize( &w, &h );
221 *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) );
222 *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) );
223 };
224
225 void wxDC::SetTextForeground( const wxColour &col )
226 {
227 if (!Ok()) return;
228 m_textForegroundColour = col;
229 };
230
231 void wxDC::SetTextBackground( const wxColour &col )
232 {
233 if (!Ok()) return;
234 m_textBackgroundColour = col;
235 };
236
237 void wxDC::SetMapMode( int mode )
238 {
239 switch (mode)
240 {
241 case MM_TWIPS:
242 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
243 break;
244 case MM_POINTS:
245 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
246 break;
247 case MM_METRIC:
248 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
249 break;
250 case MM_LOMETRIC:
251 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
252 break;
253 default:
254 case MM_TEXT:
255 SetLogicalScale( 1.0, 1.0 );
256 break;
257 };
258 if (mode != MM_TEXT)
259 {
260 m_needComputeScaleX = TRUE;
261 m_needComputeScaleY = TRUE;
262 };
263 };
264
265 void wxDC::SetUserScale( double x, double y )
266 {
267 // allow negative ? -> no
268 m_userScaleX = x;
269 m_userScaleY = y;
270 ComputeScaleAndOrigin();
271 };
272
273 void wxDC::GetUserScale( double *x, double *y )
274 {
275 if (x) *x = m_userScaleX;
276 if (y) *y = m_userScaleY;
277 };
278
279 void wxDC::SetLogicalScale( double x, double y )
280 {
281 // allow negative ?
282 m_logicalScaleX = x;
283 m_logicalScaleY = y;
284 ComputeScaleAndOrigin();
285 };
286
287 void wxDC::GetLogicalScale( double *x, double *y )
288 {
289 if (x) *x = m_logicalScaleX;
290 if (y) *y = m_logicalScaleY;
291 };
292
293 void wxDC::SetLogicalOrigin( long x, long y )
294 {
295 m_logicalOriginX = x * m_signX; // is this still correct ?
296 m_logicalOriginY = y * m_signY;
297 ComputeScaleAndOrigin();
298 };
299
300 void wxDC::GetLogicalOrigin( long *x, long *y )
301 {
302 if (x) *x = m_logicalOriginX;
303 if (y) *y = m_logicalOriginY;
304 };
305
306 void wxDC::SetDeviceOrigin( long x, long y )
307 {
308 m_externalDeviceOriginX = x;
309 m_externalDeviceOriginY = y;
310 ComputeScaleAndOrigin();
311 };
312
313 void wxDC::GetDeviceOrigin( long *x, long *y )
314 {
315 // if (x) *x = m_externalDeviceOriginX;
316 // if (y) *y = m_externalDeviceOriginY;
317 if (x) *x = m_deviceOriginX;
318 if (y) *y = m_deviceOriginY;
319 };
320
321 void wxDC::SetInternalDeviceOrigin( long x, long y )
322 {
323 m_internalDeviceOriginX = x;
324 m_internalDeviceOriginY = y;
325 ComputeScaleAndOrigin();
326 };
327
328 void wxDC::GetInternalDeviceOrigin( long *x, long *y )
329 {
330 if (x) *x = m_internalDeviceOriginX;
331 if (y) *y = m_internalDeviceOriginY;
332 };
333
334 void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
335 {
336 m_signX = (xLeftRight ? 1 : -1);
337 m_signY = (yBottomUp ? -1 : 1);
338 ComputeScaleAndOrigin();
339 };
340
341 long wxDC::DeviceToLogicalX(long x) const
342 {
343 return XDEV2LOG(x);
344 };
345
346 long wxDC::DeviceToLogicalY(long y) const
347 {
348 return YDEV2LOG(y);
349 };
350
351 long wxDC::DeviceToLogicalXRel(long x) const
352 {
353 return XDEV2LOGREL(x);
354 };
355
356 long wxDC::DeviceToLogicalYRel(long y) const
357 {
358 return YDEV2LOGREL(y);
359 };
360
361 long wxDC::LogicalToDeviceX(long x) const
362 {
363 return XLOG2DEV(x);
364 };
365
366 long wxDC::LogicalToDeviceY(long y) const
367 {
368 return YLOG2DEV(y);
369 };
370
371 long wxDC::LogicalToDeviceXRel(long x) const
372 {
373 return XLOG2DEVREL(x);
374 };
375
376 long wxDC::LogicalToDeviceYRel(long y) const
377 {
378 return YLOG2DEVREL(y);
379 };
380
381 void wxDC::CalcBoundingBox( long x, long y )
382 {
383 if (x < m_minX) m_minX = x;
384 if (y < m_minY) m_minY = y;
385 if (x > m_maxX) m_maxX = x;
386 if (y > m_maxY) m_maxY = y;
387 };
388
389 void wxDC::ComputeScaleAndOrigin(void)
390 {
391 // CMB: copy scale to see if it changes
392 double origScaleX = m_scaleX;
393 double origScaleY = m_scaleY;
394
395 m_scaleX = m_logicalScaleX * m_userScaleX;
396 m_scaleY = m_logicalScaleY * m_userScaleY;
397
398 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
399 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
400
401 // CMB: if scale has changed call SetPen to recalulate the line width
402 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
403 {
404 // this is a bit artificial, but we need to force wxDC to think
405 // the pen has changed
406 wxPen* pen = & GetPen();
407 wxPen tempPen;
408 m_pen = tempPen;
409 SetPen(* pen);
410 }
411 };
412