Many changes to the printing classes.
[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 = wxMM_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 = 0;
72 m_minX = m_minY = 0;
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( int* width, int* height ) const
217 {
218 int w = 0;
219 int h = 0;
220 GetSize( &w, &h );
221 *width = int( double(w) / (m_scaleX*m_mm_to_pix_x) );
222 *height = int( double(h) / (m_scaleY*m_mm_to_pix_y) );
223 };
224
225 // Resolution in pixels per logical inch
226 wxSize wxDC::GetPPI(void) const
227 {
228 // TODO (should probably be pure virtual)
229 return wxSize(0, 0);
230 }
231
232 void wxDC::SetTextForeground( const wxColour &col )
233 {
234 if (!Ok()) return;
235 m_textForegroundColour = col;
236 };
237
238 void wxDC::SetTextBackground( const wxColour &col )
239 {
240 if (!Ok()) return;
241 m_textBackgroundColour = col;
242 };
243
244 void wxDC::SetMapMode( int mode )
245 {
246 switch (mode)
247 {
248 case wxMM_TWIPS:
249 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
250 break;
251 case wxMM_POINTS:
252 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
253 break;
254 case wxMM_METRIC:
255 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
256 break;
257 case wxMM_LOMETRIC:
258 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
259 break;
260 default:
261 case wxMM_TEXT:
262 SetLogicalScale( 1.0, 1.0 );
263 break;
264 };
265 if (mode != wxMM_TEXT)
266 {
267 m_needComputeScaleX = TRUE;
268 m_needComputeScaleY = TRUE;
269 };
270 };
271
272 void wxDC::SetUserScale( double x, double y )
273 {
274 // allow negative ? -> no
275 m_userScaleX = x;
276 m_userScaleY = y;
277 ComputeScaleAndOrigin();
278 };
279
280 void wxDC::GetUserScale( double *x, double *y )
281 {
282 if (x) *x = m_userScaleX;
283 if (y) *y = m_userScaleY;
284 };
285
286 void wxDC::SetLogicalScale( double x, double y )
287 {
288 // allow negative ?
289 m_logicalScaleX = x;
290 m_logicalScaleY = y;
291 ComputeScaleAndOrigin();
292 };
293
294 void wxDC::GetLogicalScale( double *x, double *y )
295 {
296 if (x) *x = m_logicalScaleX;
297 if (y) *y = m_logicalScaleY;
298 };
299
300 void wxDC::SetLogicalOrigin( long x, long y )
301 {
302 m_logicalOriginX = x * m_signX; // is this still correct ?
303 m_logicalOriginY = y * m_signY;
304 ComputeScaleAndOrigin();
305 };
306
307 void wxDC::GetLogicalOrigin( long *x, long *y )
308 {
309 if (x) *x = m_logicalOriginX;
310 if (y) *y = m_logicalOriginY;
311 };
312
313 void wxDC::SetDeviceOrigin( long x, long y )
314 {
315 m_externalDeviceOriginX = x;
316 m_externalDeviceOriginY = y;
317 ComputeScaleAndOrigin();
318 };
319
320 void wxDC::GetDeviceOrigin( long *x, long *y )
321 {
322 // if (x) *x = m_externalDeviceOriginX;
323 // if (y) *y = m_externalDeviceOriginY;
324 if (x) *x = m_deviceOriginX;
325 if (y) *y = m_deviceOriginY;
326 };
327
328 void wxDC::SetInternalDeviceOrigin( long x, long y )
329 {
330 m_internalDeviceOriginX = x;
331 m_internalDeviceOriginY = y;
332 ComputeScaleAndOrigin();
333 };
334
335 void wxDC::GetInternalDeviceOrigin( long *x, long *y )
336 {
337 if (x) *x = m_internalDeviceOriginX;
338 if (y) *y = m_internalDeviceOriginY;
339 };
340
341 void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
342 {
343 m_signX = (xLeftRight ? 1 : -1);
344 m_signY = (yBottomUp ? -1 : 1);
345 ComputeScaleAndOrigin();
346 };
347
348 long wxDC::DeviceToLogicalX(long x) const
349 {
350 return XDEV2LOG(x);
351 };
352
353 long wxDC::DeviceToLogicalY(long y) const
354 {
355 return YDEV2LOG(y);
356 };
357
358 long wxDC::DeviceToLogicalXRel(long x) const
359 {
360 return XDEV2LOGREL(x);
361 };
362
363 long wxDC::DeviceToLogicalYRel(long y) const
364 {
365 return YDEV2LOGREL(y);
366 };
367
368 long wxDC::LogicalToDeviceX(long x) const
369 {
370 return XLOG2DEV(x);
371 };
372
373 long wxDC::LogicalToDeviceY(long y) const
374 {
375 return YLOG2DEV(y);
376 };
377
378 long wxDC::LogicalToDeviceXRel(long x) const
379 {
380 return XLOG2DEVREL(x);
381 };
382
383 long wxDC::LogicalToDeviceYRel(long y) const
384 {
385 return YLOG2DEVREL(y);
386 };
387
388 void wxDC::CalcBoundingBox( long x, long y )
389 {
390 if (x < m_minX) m_minX = x;
391 if (y < m_minY) m_minY = y;
392 if (x > m_maxX) m_maxX = x;
393 if (y > m_maxY) m_maxY = y;
394 };
395
396 void wxDC::ComputeScaleAndOrigin(void)
397 {
398 // CMB: copy scale to see if it changes
399 double origScaleX = m_scaleX;
400 double origScaleY = m_scaleY;
401
402 m_scaleX = m_logicalScaleX * m_userScaleX;
403 m_scaleY = m_logicalScaleY * m_userScaleY;
404
405 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
406 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
407
408 // CMB: if scale has changed call SetPen to recalulate the line width
409 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
410 {
411 // this is a bit artificial, but we need to force wxDC to think
412 // the pen has changed
413 wxPen* pen = & GetPen();
414 wxPen tempPen;
415 m_pen = tempPen;
416 SetPen(* pen);
417 }
418 };
419