PLplot: wxwidgets_dc.cpp Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
wxwidgets_dc.cpp
Go to the documentation of this file.
1 // $Id: wxwidgets_dc.cpp 12475 2013-08-09 16:21:45Z airwin $
2 //
3 // Copyright (C) 2005 Werner Smekal, Sjaak Verdoold
4 // Copyright (C) 2005 Germain Carrera Corraleche
5 // Copyright (C) 1999 Frank Huebner
6 //
7 // This file is part of PLplot.
8 //
9 // PLplot is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Library General Public License as published
11 // by the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // PLplot is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Library General Public License for more details.
18 //
19 // You should have received a copy of the GNU Library General Public License
20 // along with PLplot; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23
24 // TODO:
25 // - text clipping
26 // - implement AddToClipRegion for text correctly
27 //
28
29 // wxwidgets headers
30 #include <wx/wx.h>
31
32 #include "plDevs.h"
33
34 // plplot headers
35 #include "plplotP.h"
36
37 // std and driver headers
38 #include <cmath>
39 #include "wxwidgets.h"
40
41
42 //--------------------------------------------------------------------------
43 // wxPLDevDC::wxPLDevDC( void )
44 //
45 // Constructor of the standard wxWidgets device based on the wxPLDevBase
46 // class. Only some initialisations are done.
47 //--------------------------------------------------------------------------
48 wxPLDevDC::wxPLDevDC( void ) : wxPLDevBase( wxBACKEND_DC )
49 {
50 m_dc = NULL;
51 m_bitmap = NULL;
52 m_font = NULL;
53 underlined = false;
54 }
55
56
57 //--------------------------------------------------------------------------
58 // wxPLDevDC::~wxPLDevDC( void )
59 //
60 // The deconstructor frees memory allocated by the device.
61 //--------------------------------------------------------------------------
62 wxPLDevDC::~wxPLDevDC()
63 {
64 if ( ownGUI )
65 {
66 if ( m_dc )
67 {
68 ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap );
69 delete m_dc;
70 }
71 if ( m_bitmap )
72 delete m_bitmap;
73 }
74
75 if ( m_font )
76 delete m_font;
77 }
78
79
80 //--------------------------------------------------------------------------
81 // void wxPLDevDC::DrawLine( short x1a, short y1a, short x2a, short y2a )
82 //
83 // Draw a line from (x1a, y1a) to (x2a, y2a).
84 //--------------------------------------------------------------------------
85 void wxPLDevDC::DrawLine( short x1a, short y1a, short x2a, short y2a )
86 {
87 x1a = (short) ( x1a / scalex ); y1a = (short) ( height - y1a / scaley );
88 x2a = (short) ( x2a / scalex ); y2a = (short) ( height - y2a / scaley );
89
90 m_dc->DrawLine( (wxCoord) x1a, (wxCoord) y1a, (wxCoord) x2a, (wxCoord) y2a );
91
92 AddtoClipRegion( (int) x1a, (int) y1a, (int) x2a, (int) y2a );
93 }
94
95
96 //--------------------------------------------------------------------------
97 // void wxPLDevDC::DrawPolyline( short *xa, short *ya, PLINT npts )
98 //
99 // Draw a poly line - coordinates are in the xa and ya arrays.
100 //--------------------------------------------------------------------------
101 void wxPLDevDC::DrawPolyline( short *xa, short *ya, PLINT npts )
102 {
103 wxCoord x1a, y1a, x2a, y2a;
104
105 x2a = (wxCoord) ( xa[0] / scalex );
106 y2a = (wxCoord) ( height - ya[0] / scaley );
107 for ( PLINT i = 1; i < npts; i++ )
108 {
109 x1a = x2a; y1a = y2a;
110 x2a = (wxCoord) ( xa[i] / scalex );
111 y2a = (wxCoord) ( height - ya[i] / scaley );
112
113 m_dc->DrawLine( x1a, y1a, x2a, y2a );
114
115 AddtoClipRegion( (int) x1a, (int) y1a, (int) x2a, (int) y2a );
116 }
117 }
118
119
120 //--------------------------------------------------------------------------
121 // void wxPLDevDC::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb,
122 // PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
123 //
124 // Clear parts ((x1,y1) to (x2,y2)) of the background in color (bgr,bgg,bgb).
125 //--------------------------------------------------------------------------
126 void wxPLDevDC::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb,
127 PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
128 {
129 if ( x1 < 0 )
130 x1 = 0;
131 else
132 x1 = (PLINT) ( x1 / scalex );
133 if ( y1 < 0 )
134 y1 = 0;
135 else
136 y1 = (PLINT) ( height - y1 / scaley );
137 if ( x2 < 0 )
138 x2 = width;
139 else
140 x2 = (PLINT) ( x2 / scalex );
141 if ( y2 < 0 )
142 y2 = height;
143 else
144 y2 = (PLINT) ( height - y2 / scaley );
145
146 const wxPen oldPen = m_dc->GetPen();
147 const wxBrush oldBrush = m_dc->GetBrush();
148
149 m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( bgr, bgg, bgb ), 1, wxSOLID ) ) );
150 m_dc->SetBrush( wxBrush( wxColour( bgr, bgg, bgb ) ) );
151 m_dc->DrawRectangle( x1, y1, x2 - x1, y2 - y1 );
152
153 m_dc->SetPen( oldPen );
154 m_dc->SetBrush( oldBrush );
155
156 AddtoClipRegion( x1, y1, x2, y2 );
157 }
158
159
160 //--------------------------------------------------------------------------
161 // void wxPLDevDC::FillPolygon( PLStream *pls )
162 //
163 // Draw a filled polygon.
164 //--------------------------------------------------------------------------
165 void wxPLDevDC::FillPolygon( PLStream *pls )
166 {
167 wxPoint *points = new wxPoint[pls->dev_npts];
168 wxCoord xoffset = 0;
169 wxCoord yoffset = 0;
170
171 for ( int i = 0; i < pls->dev_npts; i++ )
172 {
173 points[i].x = (int) ( pls->dev_x[i] / scalex );
174 points[i].y = (int) ( height - pls->dev_y[i] / scaley );
175 if ( i > 0 )
176 AddtoClipRegion( points[i - 1].x, points[i - 1].y, points[i].x, points[i].y );
177 }
178
179 if ( pls->dev_eofill )
180 {
181 m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxODDEVEN_RULE );
182 }
183 else
184 {
185 m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxWINDING_RULE );
186 }
187 delete[] points;
188 }
189
190
191 //--------------------------------------------------------------------------
192 // void wxPLDevDC::BlitRectangle( wxDC* dc, int vX, int vY,
193 // int vW, int vH )
194 //
195 // Copy/Blit a rectangle ((vX,vY) to (vX+vW,vY+vH)) into given dc.
196 //--------------------------------------------------------------------------
197 void wxPLDevDC::BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH )
198 {
199 if ( m_dc )
200 dc->Blit( vX, vY, vW, vH, m_dc, vX, vY );
201 }
202
203
204 //--------------------------------------------------------------------------
205 // void wxPLDevDC::CreateCanvas( void )
206 //
207 // Create canvas (bitmap and dc) if the driver provides the GUI.
208 //--------------------------------------------------------------------------
209 void wxPLDevDC::CreateCanvas()
210 {
211 if ( ownGUI )
212 {
213 if ( !m_dc )
214 m_dc = new wxMemoryDC();
215
216 ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap ); // deselect bitmap
217 if ( m_bitmap )
218 delete m_bitmap;
219 m_bitmap = new wxBitmap( bm_width, bm_height, 32 );
220 ( (wxMemoryDC *) m_dc )->SelectObject( *m_bitmap ); // select new bitmap
221 }
222 }
223
224
225 //--------------------------------------------------------------------------
226 // void wxPLDevDC::SetWidth( PLStream *pls )
227 //
228 // Set the width of the drawing pen.
229 //--------------------------------------------------------------------------
230 void wxPLDevDC::SetWidth( PLStream *pls )
231 {
232 m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ),
233 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
234 }
235
236
237 //--------------------------------------------------------------------------
238 // void wxPLDevDC::SetColor0( PLStream *pls )
239 //
240 // Set color from colormap 0.
241 //--------------------------------------------------------------------------
242 void wxPLDevDC::SetColor0( PLStream *pls )
243 {
244 m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ),
245 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
246 m_dc->SetBrush( wxBrush( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ) ) );
247 }
248
249
250 //--------------------------------------------------------------------------
251 // void wxPLDevDC::SetColor1( PLStream *pls )
252 //
253 // Set color from colormap 1.
254 //--------------------------------------------------------------------------
255 void wxPLDevDC::SetColor1( PLStream *pls )
256 {
257 m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ),
258 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
259 m_dc->SetBrush( wxBrush( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ) ) );
260 }
261
262
263 //--------------------------------------------------------------------------
264 // void wxPLDevDC::SetExternalBuffer( void* dc )
265 //
266 // Adds a dc to the device. In that case, the drivers doesn't provide
267 // a GUI.
268 //--------------------------------------------------------------------------
269 void wxPLDevDC::SetExternalBuffer( void* dc )
270 {
271 m_dc = (wxDC *) dc; // Add the dc to the device
272 ready = true;
273 ownGUI = false;
274 }
275
276
277 #ifdef PL_HAVE_FREETYPE
278
279 //--------------------------------------------------------------------------
280 // void wxPLDevDC::PutPixel( short x, short y, PLINT color )
281 //
282 // Draw a pixel in color color @ (x,y).
283 //--------------------------------------------------------------------------
284 void wxPLDevDC::PutPixel( short x, short y, PLINT color )
285 {
286 const wxPen oldpen = m_dc->GetPen();
287 m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( GetRValue( color ), GetGValue( color ), GetBValue( color ) ),
288 1, wxSOLID ) ) );
289 m_dc->DrawPoint( x, y );
290 AddtoClipRegion( x, y, x, y );
291 m_dc->SetPen( oldpen );
292 }
293
294
295 //--------------------------------------------------------------------------
296 // void wxPLDevDC::PutPixel( short x, short y )
297 //
298 // Draw a pixel in current color @ (x,y).
299 //--------------------------------------------------------------------------
300 void wxPLDevDC::PutPixel( short x, short y )
301 {
302 m_dc->DrawPoint( x, y );
303 AddtoClipRegion( x, y, x, y );
304 }
305
306
307 //--------------------------------------------------------------------------
308 // PLINT wxPLDevDC::GetPixel( short x, short y )
309 //
310 // Get color information from pixel @ (x,y).
311 //--------------------------------------------------------------------------
312 PLINT wxPLDevDC::GetPixel( short x, short y )
313 {
314 #ifdef __WXGTK__
315 // The GetPixel method is incredible slow for wxGTK. Therefore we set the colour
316 // always to the background color, since this is the case anyway 99% of the time.
317 PLINT bgr, bgg, bgb; // red, green, blue
318 (void) x; (void) y; // Cast to void to silence compiler warnings about unused parameters
319 plgcolbg( &bgr, &bgg, &bgb ); // get background color information
320 return RGB( bgr, bgg, bgb );
321 #else
322 wxColour col;
323 m_dc->GetPixel( x, y, &col );
324 return RGB( col.Red(), col.Green(), col.Blue() );
325 #endif
326 }
327
328 #endif // PL_HAVE_FREETYPE
329
330
331 //--------------------------------------------------------------------------
332 // void wxPLDevDC::PSDrawTextToDC( char* utf8_string, bool drawText )
333 //
334 // Draw utf8 text to screen if drawText==true. Otherwise determine
335 // width and height of text.
336 //--------------------------------------------------------------------------
337 void wxPLDevDC::PSDrawTextToDC( char* utf8_string, bool drawText )
338 {
339 wxCoord w, h, d, l;
340
341 wxString str( wxConvUTF8.cMB2WC( utf8_string ), *wxConvCurrent );
342
343 m_dc->GetTextExtent( str, &w, &h, &d, &l );
344
345 if ( drawText )
346 {
347 m_dc->DrawRotatedText( str, (wxCoord) ( posX - yOffset / scaley * sin_rot ),
348 (wxCoord) ( height - (wxCoord) ( posY + yOffset * cos_rot / scaley ) ),
349 rotation * 180.0 / M_PI );
350 posX += (PLINT) ( w * cos_rot );
351 posY += (PLINT) ( w * sin_rot );
352 }
353
354 textWidth += w;
355
356 //keep track of the height of superscript text, the depth of subscript
357 //text and the height of regular text
358 if ( yOffset > 0.0001 )
359 {
360 //determine the height the text would have if it were full size
361 double currentOffset = yOffset;
362 double currentHeight = h;
363 while ( currentOffset > 0.0001 )
364 {
365 currentOffset -= scaley * fontSize * fontScale / 2.;
366 currentHeight *= 1.25;
367 }
368 textHeight = (wxCoord) textHeight > ( currentHeight )
369 ? textHeight
370 : currentHeight;
371 //work out the height including superscript
372 superscriptHeight = superscriptHeight > ( currentHeight + yOffset / scaley )
373 ? superscriptHeight
374 : static_cast<int>( ( currentHeight + yOffset / scaley ) );
375 }
376 else if ( yOffset < -0.0001 )
377 {
378 //determine the height the text would have if it were full size
379 double currentOffset = yOffset;
380 double currentHeight = h;
381 double currentDepth = d;
382 while ( currentOffset < -0.0001 )
383 {
384 currentOffset += scaley * fontSize * fontScale * 1.25 / 2.;
385 currentHeight *= 1.25;
386 currentDepth *= 1.25;
387 }
388 textHeight = (wxCoord) textHeight > currentHeight ? textHeight : currentHeight;
389 //work out the additional depth for subscript note an assumption has been made
390 //that the font size of (non-superscript and non-subscript) text is the same
391 //along a line. Currently there is no escape to change font size mid string
392 //so this should be fine
393 subscriptDepth = (wxCoord) subscriptDepth > ( ( -yOffset / scaley + h + d ) - ( currentDepth + textHeight ) )
394 ? subscriptDepth
395 : ( ( -yOffset / scaley + h + d ) - ( currentDepth + textHeight ) );
396 subscriptDepth = subscriptDepth > 0 ? subscriptDepth : 0;
397 }
398 else
399 textHeight = (wxCoord) textHeight > ( h ) ? textHeight : h;
400
401 memset( utf8_string, '\0', max_string_length );
402 }
403
404
405 //--------------------------------------------------------------------------
406 // void wxPLDevDC::PSSetFont( PLUNICODE fci )
407 //
408 // Set font defined by fci.
409 //--------------------------------------------------------------------------
410 void wxPLDevDC::PSSetFont( PLUNICODE fci )
411 {
412 unsigned char fontFamily, fontStyle, fontWeight;
413
414 plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY );
415 plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE );
416 plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT );
417
418 if ( m_font )
419 delete m_font;
420
421 m_font = wxFont::New( (int) ( fontSize * fontScale < 4 ? 4 : fontSize * fontScale ),
422 fontFamilyLookup[fontFamily],
423 fontStyleLookup[fontStyle] | fontWeightLookup[fontWeight] );
424 m_font->SetUnderlined( underlined );
425 m_dc->SetFont( *m_font );
426 }
427
428
429 //--------------------------------------------------------------------------
430 // void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
431 //
432 // This is the main function which processes the unicode text strings.
433 // Font size, rotation and color are set, width and height of the
434 // text string is determined and then the string is drawn to the canvas.
435 //--------------------------------------------------------------------------
436 void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
437 {
438 // Check that we got unicode, warning message and return if not
439 if ( args->unicode_array_len == 0 )
440 {
441 printf( "Non unicode string passed to the wxWidgets driver, ignoring\n" );
442 return;
443 }
444
445 // Check that unicode string isn't longer then the max we allow
446 if ( args->unicode_array_len >= 500 )
447 {
448 printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
449 return;
450 }
451
452 // Calculate the font size (in pixels)
453 fontSize = pls->chrht * VIRTUAL_PIXELS_PER_MM / scaley * 1.3;
454
455 // Use PLplot core routine to get the corners of the clipping rectangle
456 PLINT rcx[4], rcy[4];
457 difilt_clip( rcx, rcy );
458
459 wxPoint cpoints[4];
460 for ( int i = 0; i < 4; i++ )
461 {
462 cpoints[i].x = rcx[i] / scalex;
463 cpoints[i].y = height - rcy[i] / scaley;
464 }
465 wxDCClipper clip( *m_dc, wxRegion( 4, cpoints ) );
466
467 // calculate rotation of text
468 plRotationShear( args->xform, &rotation, &shear, &stride );
469 rotation -= pls->diorot * M_PI / 2.0;
470 cos_rot = cos( rotation );
471 sin_rot = sin( rotation );
472
473 // Set font color
474 m_dc->SetTextForeground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );
475 m_dc->SetTextBackground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );
476
477 PLUNICODE *lineStart = args->unicode_array;
478 int lineLen = 0;
479 bool lineFeed = false;
480 bool carriageReturn = false;
481 wxCoord paraHeight = 0;
482 // Get the curent font
483 fontScale = 1.0;
484 yOffset = 0.0;
485 plgfci( &fci );
486 PSSetFont( fci );
487 while ( lineStart != args->unicode_array + args->unicode_array_len )
488 {
489 while ( lineStart + lineLen != args->unicode_array + args->unicode_array_len
490 && *( lineStart + lineLen ) != (PLUNICODE) '\n' )
491 {
492 lineLen++;
493 }
494 //set line feed for the beginning of this line and
495 //carriage return for the end
496 lineFeed = carriageReturn;
497 carriageReturn = lineStart + lineLen != args->unicode_array + args->unicode_array_len
498 && *( lineStart + lineLen ) == (PLUNICODE) ( '\n' );
499 if ( lineFeed )
500 paraHeight += textHeight + subscriptDepth;
501
502 //remember the text parameters so they can be restored
503 double startingFontScale = fontScale;
504 double startingYOffset = yOffset;
505 PLUNICODE startingFci = fci;
506
507 // determine extent of text
508 posX = args->x / scalex;
509 posY = args->y / scaley;
510
511 PSDrawText( lineStart, lineLen, false );
512
513 if ( lineFeed && superscriptHeight > textHeight )
514 paraHeight += superscriptHeight - textHeight;
515
516 // actually draw text, resetting the font first
517 fontScale = startingFontScale;
518 yOffset = startingYOffset;
519 fci = startingFci;
520 PSSetFont( fci );
521 posX = (PLINT) ( args->x / scalex - ( args->just * textWidth ) * cos_rot - ( 0.5 * textHeight - paraHeight * lineSpacing ) * sin_rot ); //move to set alignment
522 posY = (PLINT) ( args->y / scaley - ( args->just * textWidth ) * sin_rot + ( 0.5 * textHeight - paraHeight * lineSpacing ) * cos_rot );
523 PSDrawText( lineStart, lineLen, true ); //draw text
524
525 lineStart += lineLen;
526 if ( carriageReturn )
527 lineStart++;
528 lineLen = 0;
529 }
530 //posX = args->x;
531 //posY = args->y;
532 //PSDrawText( args->unicode_array, args->unicode_array_len, false );
533
534 //posX = (PLINT) ( args->x - ( ( args->just * textWidth ) * cos_rot + ( 0.5 * textHeight ) * sin_rot ) * scalex );
535 //posY = (PLINT) ( args->y - ( ( args->just * textWidth ) * sin_rot - ( 0.5 * textHeight ) * cos_rot ) * scaley );
536 //PSDrawText( args->unicode_array, args->unicode_array_len, true );
537
538 AddtoClipRegion( 0, 0, width, height );
539 }
540
541