PLplot: wxwidgets_dev.cpp Source File

PLplot 5.15.0

wxwidgets_dev.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015-2017 Phil Rosenberg
2 // Copyright (C) 2017-2018 Alan W. Irwin
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 #define DEBUG
25 #define NEED_PLDEBUG
26
27 // Set this to help when debugging wxPLViewer issues. It uses a memory
28 // map name without random characters and does not execute the viewer,
29 // allowing the user to execute the viewer in a debugger
30 //#define WXPLVIEWER_DEBUG
31
32 // Headers needed for Rand
33 #ifdef _WIN32
34 // This include must occur before any other include of stdlib.h due to
35 // the #define _CRT_RAND_S
36 #define _CRT_RAND_S
37 #include <stdlib.h>
38 #else
39 #include <fstream>
40 #endif
41
42 // PLplot headers
43 #include "plDevs.h"
44 #include "wxwidgets.h" // includes wx/wx.h
45
46 // wxwidgets headers
47 #include <wx/dir.h>
48 #include <wx/ustring.h>
49
50 // std and driver headers
51 #include <cmath>
52 #include <limits>
53
54 // Needed for cerr, etc.
55 #if defined ( WXPLVIEWER_DEBUG ) || defined ( PLPLOT_WX_DEBUG_OUTPUT )
56 #include <iostream>
57 #endif
58
59 //--------------------------------------------------------------------------
60 // PlDevice::PlDevice()
61 //
62 // Constructor for wxPLDevice
63 //--------------------------------------------------------------------------
64 PlDevice::PlDevice()
65 {
66 m_prevSymbol = 0;
67 m_prevBaseFontSize = 0.;
68 m_prevLevel = 0;
69 m_prevFci = 0;
70 m_prevSymbolWidth = 0;
71 m_prevSymbolHeight = 0;
72 }
73
74 //--------------------------------------------------------------------------
75 // void wxPLDevice::DrawText( PLStream* pls, EscText* args )
76 //
77 // This is the main function which processes the unicode text strings.
78 // Font size, rotation and color are set, width and height of the
79 // text string is determined and then the string is drawn to the canvas.
80 //--------------------------------------------------------------------------
81 void PlDevice::drawText( PLStream* pls, EscText* args )
82 {
83 // Split the text into lines separated by forced linebreak '\n' characters
84 // inserted by the user.
85 typedef std::pair< PLUNICODE *, PLUNICODE *> uniIterPair;
86 PLUNICODE *textEnd = args->unicode_array + args->unicode_array_len;
87 PLUNICODE lf = PLUNICODE( '\n' );
88 std::vector< uniIterPair > lines( 1, uniIterPair( args->unicode_array, textEnd ) );
89 for ( PLUNICODE * uni = args->unicode_array; uni != textEnd; ++uni )
90 {
91 if ( *uni == lf )
92 {
93 lines.back().second = uni;
94 lines.push_back( uniIterPair( uni + 1, textEnd ) );
95 }
96 }
97
98 // Check that we got unicode, warning message and return if not
99 if ( args->unicode_array_len == 0 )
100 {
101 printf( "Non unicode string passed to the wxWidgets driver, ignoring\n" );
102 return;
103 }
104
105 // Check that unicode string isn't longer then the max we allow
106 if ( args->unicode_array_len >= 500 )
107 {
108 printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
109 return;
110 }
111
112 // Calculate the font size (in pt)
113 // PLplot saves it in mm (bizarre units!)
114 PLFLT baseFontSize = pls->chrht * PLPLOT_POINTS_PER_INCH / PLPLOT_MM_PER_INCH;
115
116 //initialize the text state
117 PLUNICODE currentFci;
118 plgfci( &currentFci );
119 bool currentUnderlined = false;
120
121 //Get the size of each line. Even for left aligned text
122 //we still need the text height to vertically align text
123 std::vector<wxCoord> lineWidths( lines.size() );
124 std::vector<wxCoord> lineHeights( lines.size() );
125 std::vector<wxCoord> lineDepths( lines.size() );
126 {
127 // Get the text length without drawing it. Also, determine
128 // lineWidths, lineHeights, and lineDepths arrays that are required
129 // for the actual draw.
130 wxCoord paraWidth = 0;
131 wxCoord paraHeight = 0;
132 PLUNICODE testFci = currentFci;
133 bool testUnderlined = currentUnderlined = false;
134 PLFLT identityMatrix[6];
135 plP_affine_identity( identityMatrix );
136 for ( size_t i = 0; i < lines.size(); ++i )
137 {
138 DrawTextLine( lines[i].first, lines[i].second - lines[i].first, 0, 0, 0, 0, identityMatrix, baseFontSize, false,
139 testUnderlined, testFci,
140 0, 0, 0, 0.0, lineWidths[i], lineHeights[i], lineDepths[i] );
141 paraWidth = MAX( paraWidth, lineWidths[i] );
142 paraHeight += lineHeights[i] + lineDepths[i];
143 }
144 pls->string_length = paraWidth / pls->xpmm;
145 }
146
147 if ( !pls->get_string_length )
148 {
149 // Draw the text string if requested by PLplot. The needed lineWidths,
150 // lineHeights, and lineDepths arrays are determined above.
151 wxCoord cumSumHeight = 0;
152 // Plplot doesn't include plot orientation in args->xform, so we must
153 // rotate the text if needed;
154 PLFLT textTransform[6];
155 PLFLT diorot = pls->diorot - 4.0 * floor( pls->diorot / 4.0 ); //put diorot in range 0-4
156 textTransform[0] = args->xform[0];
157 textTransform[2] = args->xform[1];
158 textTransform[1] = args->xform[2];
159 textTransform[3] = args->xform[3];
160 textTransform[4] = 0.0;
161 textTransform[5] = 0.0;
162 PLFLT diorotTransform[6];
163 if ( diorot == 0.0 )
164 {
165 diorotTransform[0] = 1;
166 diorotTransform[1] = 0;
167 diorotTransform[2] = 0;
168 diorotTransform[3] = 1;
169 }
170 else if ( diorot == 1.0 )
171 {
172 diorotTransform[0] = 0;
173 diorotTransform[1] = -1;
174 diorotTransform[2] = 1;
175 diorotTransform[3] = 0;
176 }
177 else if ( diorot == 2.0 )
178 {
179 diorotTransform[0] = -1;
180 diorotTransform[1] = 0;
181 diorotTransform[2] = 0;
182 diorotTransform[3] = -1;
183 }
184 else if ( diorot == 3.0 )
185 {
186 diorotTransform[0] = 0;
187 diorotTransform[1] = 1;
188 diorotTransform[2] = -1;
189 diorotTransform[3] = 0;
190 }
191 else
192 {
193 PLFLT angle = diorot * M_PI / 2.0;
194 PLFLT cosAngle = cos( angle );
195 PLFLT sinAngle = sin( angle );
196 diorotTransform[0] = cosAngle;
197 diorotTransform[1] = -sinAngle;
198 diorotTransform[2] = sinAngle;
199 diorotTransform[3] = cosAngle;
200 }
201 diorotTransform[4] = 0;
202 diorotTransform[5] = 0;
203
204 PLFLT finalTransform[6];
205 memcpy( finalTransform, textTransform, sizeof ( PLFLT ) * 6 );
206 plP_affine_multiply( finalTransform, textTransform, diorotTransform );
207
208 std::vector<wxCoord> lineWidths_ignored( lines.size() );
209 std::vector<wxCoord> lineHeights_ignored( lines.size() );
210 std::vector<wxCoord> lineDepths_ignored( lines.size() );
211 for ( size_t i = 0; i < lines.size(); ++i )
212 {
213 DrawTextLine( lines[i].first, lines[i].second - lines[i].first,
214 args->x,
215 args->y,
216 -lineWidths[i] * args->just, 0.5 * ( lineHeights[i] ) - cumSumHeight,
217 finalTransform, baseFontSize, true,
218 currentUnderlined,
219 currentFci, pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a, lineWidths_ignored[i],
220 lineHeights_ignored[i], lineDepths_ignored[i] );
221
222 // Ignore the ignored versions even though gdb tells me
223 // (AWI) they are the same as the unignored versions
224 // determined above for the DrawText false case (as
225 // expected from inspection of the DrawTextLine code).
226 cumSumHeight += lineHeights[i] + lineDepths[i];
227 }
228 }
229 }
230
231 // This function will draw a line of text given by ucs4 with ucs4Len
232 // characters. The ucs4 argument must not contain any newline characters.
233 // basefontSize is the size of a full size character in points. Pass
234 // in underlined flag and fci for the beginning of the line. On
235 // return they will be filled with the values at the end of the line.
236 // On return textWidth, textHeigth and textDepth will be filled with
237 // the width, ascender height and descender depth of the text string.
238 // If drawText is true the text will actually be drawn. If it is
239 // false the size will be calculated but the text will not be
240 // rendered.
241
242 void PlDevice::DrawTextLine( PLUNICODE* ucs4, int ucs4Len, wxCoord xOrigin, wxCoord yOrigin, wxCoord x, wxCoord y, PLFLT *transform, PLFLT baseFontSize, bool drawText, bool &underlined, PLUNICODE &fci, unsigned char red, unsigned char green, unsigned char blue, PLFLT alpha, wxCoord &textWidth, wxCoord &textHeight, wxCoord &textDepth )
243 {
244 PLINT level = 0;
245 PLFLT oldScale;
246 PLFLT Scale = 1.;
247 PLFLT scaledFontSize = baseFontSize;
248 PLFLT oldOffset;
249 PLFLT Offset = 0.;
250 PLFLT yScale;
251 PLFLT scaledOffset = 0.;
252
253 // Factor of 1.2 is an empirical correction to work around a bug
254 // where the calculated symmetrical subscript and superscript
255 // offset arguments of DrawTextSection are rendered in that
256 // routine in an asymmetical way (with subscript levels having a
257 // differently rendered offset than the corresponding superscript
258 // level). Of course, fixing this DrawTextSection bug is far
259 // preferable to this workaround, but I have been unable to find
260 // that bug in DrawTextSection so I am leaving this ultimate fix
261 // until later.
262
263 PLFLT empiricalSymmetricFactor = 1.2;
264
265 wxCoord sectionWidth;
266 wxCoord sectionHeight;
267 wxCoord sectionDepth;
268
269 // check if we have the same symbol as last time - only do this for single characters
270 // (e.g., typical plstring use).
271 if ( !drawText
272 && ucs4Len == 1
273 && ucs4[0] == m_prevSymbol
274 && baseFontSize == m_prevBaseFontSize
275 && level == m_prevLevel
276 && fci == m_prevFci )
277 {
278 textWidth = m_prevSymbolWidth;
279 textHeight = m_prevSymbolHeight;
280 textDepth = m_prevSymbolDepth;
281 return;
282 }
283
284 wxString section;
285
286 PLFLT sectionTransform[6];
287 memcpy( sectionTransform, transform, sizeof ( sectionTransform ) );
288
289 // Get PLplot escape character
290 char plplotEsc;
291 plgesc( &plplotEsc );
292
293 // Reset the size metrics
294 textWidth = 0;
295 textHeight = 0;
296 textDepth = 0;
297
298 int i = 0;
299 while ( i < ucs4Len )
300 {
301 if ( ucs4[i] == (PLUNICODE) plplotEsc )
302 {
303 // We found an escape character. Move to the next character to see what we need to do next
304 ++i;
305 if ( ucs4[i] == (PLUNICODE) plplotEsc )
306 {
307 // Add the actual escape character to the string
308 section += wxUString( (wxChar32) ucs4[i] );
309 }
310 else
311 {
312 // We have a change of state. Output the string so far
313 DrawTextSection( section, xOrigin, yOrigin, x + textWidth, y + scaledOffset, transform,
314 scaledFontSize, drawText, underlined, fci, red, green, blue, alpha, yScale, sectionWidth, sectionHeight, sectionDepth );
315 textWidth += sectionWidth;
316 textHeight = MAX( textHeight, sectionHeight + scaledOffset );
317 textDepth = MAX( textDepth, sectionDepth - scaledOffset );
318 section = wxEmptyString;
319
320 // Act on the escape character
321 if ( ucs4[i] == (PLUNICODE) 'u' )
322 {
323 // Superscript escape
324
325 // y, textHeight, and textDepth are all scaled
326 // quantities so any offset-related variable that
327 // is linearly combined with them such as
328 // scaledOffset must be scaled as well. Offset is
329 // always positive so the last factor is to give
330 // scaledOffset the correct sign depending on
331 // level.
332 plP_script_scale( TRUE, &level, &oldScale, &Scale, &oldOffset, &Offset );
333 scaledFontSize = baseFontSize * Scale;
334 scaledOffset = yScale * Offset * baseFontSize * ( level > 0 ? 1.0 / empiricalSymmetricFactor : -1.0 * empiricalSymmetricFactor );
335 }
336 else if ( ucs4[i] == (PLUNICODE) 'd' )
337 {
338 // Subscript escape
339
340 // y, textHeight, and textDepth are all scaled
341 // quantities so any offset-related variable that
342 // is linearly combined with them such as
343 // scaledOffset must be scaled as well. Offset is
344 // always positive so the last factor is to give
345 // scaledOffset the correct sign depending on
346 // level.
347 plP_script_scale( FALSE, &level, &oldScale, &Scale, &oldOffset, &Offset );
348 scaledFontSize = baseFontSize * Scale;
349 scaledOffset = yScale * Offset * baseFontSize * ( level > 0 ? 1.0 / empiricalSymmetricFactor : -1.0 * empiricalSymmetricFactor );
350 }
351 else if ( ucs4[i] == (PLUNICODE) '-' ) // underline
352 underlined = !underlined;
353 else if ( ucs4[i] == (PLUNICODE) '+' ) // overline
354 { // not implemented yet
355 }
356 }
357 }
358 else if ( ucs4[i] >= PL_FCI_MARK )
359 {
360 // A font change
361 // draw string so far
362 DrawTextSection( section, xOrigin, yOrigin, x + textWidth, y + scaledOffset, transform,
363 scaledFontSize, drawText, underlined, fci, red, green, blue, alpha, yScale, sectionWidth, sectionHeight, sectionDepth );
364 textWidth += sectionWidth;
365 textHeight = MAX( textHeight, sectionHeight + scaledOffset );
366 textDepth = MAX( textDepth, sectionDepth - scaledOffset );
367 section = wxEmptyString;
368
369 // Get new fci
370 fci = ucs4[i];
371 }
372 else
373 {
374 // Just a regular character - add it to the string
375 section += wxUString( (wxChar32) ucs4[i] );
376 }
377
378 ++i;
379 }
380
381 // We have reached the end of the string. Draw the last section.
382 DrawTextSection( section, xOrigin, yOrigin, x + textWidth, y + scaledOffset, transform,
383 scaledFontSize, drawText, underlined, fci, red, green, blue, alpha, yScale, sectionWidth, sectionHeight, sectionDepth );
384 textWidth += sectionWidth;
385 textHeight = MAX( textHeight, sectionHeight + scaledOffset );
386 textDepth = MAX( textDepth, sectionDepth - scaledOffset );
387
388 // If this was a single character remember its size as it is
389 // likely to be requested repeatedly (e.g., typical plstring use).
390 if ( ucs4Len == 1 )
391 {
392 m_prevSymbol = ucs4[0];
393 m_prevBaseFontSize = baseFontSize;
394 m_prevLevel = level;
395 m_prevFci = fci;
396 m_prevSymbolWidth = textWidth;
397 m_prevSymbolHeight = textHeight;
398 m_prevSymbolDepth = textDepth;
399 }
400 }
401
402 //--------------------------------------------------------------------------
403 // Scaler class
404 // This class changes the logical scale of a dc on construction and resets
405 // it to its original value on destruction. It is ideal for making temporary
406 // changes to the scale and guaranteeing that the scale gets set back.
407 //--------------------------------------------------------------------------
408 class Scaler
409 {
410 public:
411 Scaler( wxDC * dc, double xScale, double yScale )
412 {
413 m_dc = dc;
414 if ( m_dc )
415 {
416 dc->GetUserScale( &m_xScaleOld, &m_yScaleOld );
417 dc->SetUserScale( xScale, yScale );
418 }
419 }
420 ~Scaler( )
421 {
422 if ( m_dc )
423 m_dc->SetUserScale( m_xScaleOld, m_yScaleOld );
424 }
425 private:
426 wxDC *m_dc;
427 double m_xScaleOld;
428 double m_yScaleOld;
429 Scaler & operator=( const Scaler & );
430 Scaler ( const Scaler & );
431 };
432
433 //--------------------------------------------------------------------------
434 // OriginChanger class
435 // This class changes the logical origin of a dc on construction and resets
436 // it to its original value on destruction. It is ideal for making temporary
437 // changes to the origin and guaranteeing that the scale gets set back.
438 //--------------------------------------------------------------------------
439 class OriginChanger
440 {
441 public:
442 OriginChanger( wxDC * dc, wxCoord xOrigin, wxCoord yOrigin )
443 {
444 m_dc = dc;
445 if ( m_dc )
446 {
447 dc->GetLogicalOrigin( &m_xOriginOld, &m_yOriginOld );
448 dc->SetLogicalOrigin( xOrigin, yOrigin );
449 }
450 }
451 ~OriginChanger( )
452 {
453 if ( m_dc )
454 m_dc->SetLogicalOrigin( m_xOriginOld, m_yOriginOld );
455 }
456 private:
457 wxDC *m_dc;
458 wxCoord m_xOriginOld;
459 wxCoord m_yOriginOld;
460 OriginChanger & operator=( const OriginChanger & );
461 OriginChanger ( const OriginChanger & );
462 };
463
464 //--------------------------------------------------------------------------
465 // DrawingObjectsChanger class
466 // This class changes the pen and brush of a dc on construction and resets
467 // them to their original values on destruction. It is ideal for making temporary
468 // changes to the pen and brush and guaranteeing that they get set back.
469 //--------------------------------------------------------------------------
470 class DrawingObjectsChanger
471 {
472 public:
473 DrawingObjectsChanger( wxDC *dc, const wxPen &pen, const wxBrush &brush )
474 {
475 m_dc = dc;
476 if ( m_dc )
477 {
478 m_pen = dc->GetPen();
479 m_brush = dc->GetBrush();
480 dc->SetPen( pen );
481 dc->SetBrush( brush );
482 }
483 }
484 ~DrawingObjectsChanger()
485 {
486 if ( m_dc )
487 {
488 m_dc->SetPen( m_pen );
489 m_dc->SetBrush( m_brush );
490 }
491 }
492 private:
493 wxDC *m_dc;
494 wxPen m_pen;
495 wxBrush m_brush;
496 DrawingObjectsChanger & operator=( const DrawingObjectsChanger & );
497 DrawingObjectsChanger ( const DrawingObjectsChanger & );
498 };
499
500 //--------------------------------------------------------------------------
501 //TextObjectsSaver class
502 //This class saves the text rendering details of a dc on construction and
503 //resets them to their original values on destruction. It can be used to
504 //ensure the restoration of state when a scope is exited
505 //--------------------------------------------------------------------------
506 class TextObjectsSaver
507 {
508 public:
509 TextObjectsSaver( wxDC *dc )
510 {
511 m_dc = dc;
512 if ( m_dc )
513 {
514 m_font = dc->GetFont();
515 m_textForeground = dc->GetTextForeground();
516 m_textBackground = dc->GetTextBackground();
517 }
518 }
519 ~TextObjectsSaver()
520 {
521 if ( m_dc )
522 {
523 m_dc->SetTextForeground( m_textForeground );
524 m_dc->SetTextBackground( m_textBackground );
525 m_dc->SetFont( m_font );
526 }
527 }
528 private:
529 wxDC *m_dc;
530 wxFont m_font;
531 wxColour m_textForeground;
532 wxColour m_textBackground;
533 TextObjectsSaver & operator=( const TextObjectsSaver & );
534 TextObjectsSaver ( const TextObjectsSaver & );
535 };
536
537 //--------------------------------------------------------------------------
538 // TextObjectsChanger class
539 // This class changes the font and text colours of a dc on construction and resets
540 // them to their original values on destruction. It is ideal for making temporary
541 // changes to the text and guaranteeing that they get set back.
542 //--------------------------------------------------------------------------
543 class TextObjectsChanger
544 {
545 public:
546 TextObjectsChanger( wxDC *dc, const wxFont &font, const wxColour &textForeground, const wxColour &textBackground )
547 : m_saver( dc )
548 {
549 if ( dc )
550 {
551 dc->SetTextForeground( textForeground );
552 dc->SetTextBackground( textBackground );
553 dc->SetFont( font );
554 }
555 }
556 TextObjectsChanger( wxDC *dc, const wxFont &font )
557 : m_saver( dc )
558 {
559 if ( dc )
560 dc->SetFont( font );
561 }
562 TextObjectsChanger( wxDC *dc, FontGrabber &fontGrabber, PLUNICODE fci, PLFLT size, bool underlined, const wxColour &textForeground, const wxColour &textBackground )
563 : m_saver( dc )
564 {
565 if ( dc )
566 {
567 wxFont font = fontGrabber.GetFont( fci, size, underlined ).getWxFont();
568 dc->SetTextForeground( textForeground );
569 dc->SetTextBackground( textBackground );
570 dc->SetFont( font );
571 }
572 }
573 private:
574 TextObjectsSaver m_saver;
575 TextObjectsChanger & operator=( const TextObjectsChanger & );
576 TextObjectsChanger ( const TextObjectsChanger & );
577 };
578
579 //--------------------------------------------------------------------------
580 // Clipper class
581 // This class changes the clipping region of a dc on construction and restores
582 // it to its previous region on destruction. It is ideal for making temporary
583 // changes to the clip region and guaranteeing that the scale gets set back.
584 //
585 // It turns out that clipping is mostly broken for wxGCDC - see
586 // http://trac.wxwidgets.org/ticket/17013. So there are a lot of things in
587 // this class to work around those bugs. In particular you should check
588 // isEveryThingClipped before drawing as I'm not sure if non-overlapping
589 //clip regions behave properly.
590 //--------------------------------------------------------------------------
591 class Clipper
592 {
593 public:
594 Clipper( wxDC * dc, const wxRect &rect )
595 {
596 m_dc = dc;
597 m_clipEverything = true;
598 if ( m_dc )
599 {
600 dc->GetClippingBox( m_boxOld );
601 wxRect newRect = rect;
602 m_clipEverything = !( newRect.Intersects( m_boxOld )
603 || ( m_boxOld.width == 0 && m_boxOld.height == 0 ) );
604 if ( m_clipEverything )
605 dc->SetClippingRegion( wxRect( -1, -1, 1, 1 ) ); //not sure if this works
606 else
607 dc->SetClippingRegion( rect );
608 }
609 }
610 ~Clipper( )
611 {
612 if ( m_dc )
613 {
614 m_dc->DestroyClippingRegion();
615 m_dc->SetClippingRegion( wxRect( 0, 0, 0, 0 ) );
616 m_dc->DestroyClippingRegion();
617 if ( m_boxOld.width != 0 && m_boxOld.height != 0 )
618 m_dc->SetClippingRegion( m_boxOld );
619 }
620 }
621 bool isEverythingClipped()
622 {
623 return m_clipEverything;
624 }
625 private:
626 wxDC *m_dc;
627 wxRect m_boxOld;
628 bool m_clipEverything;
629 Clipper & operator=( const Clipper & );
630 Clipper ( const Clipper & );
631 };
632
633 //--------------------------------------------------------------------------
634 // class Rand
635 // This is a simple random number generator class, created solely so that
636 // random numbers can be generated in this file without "contaminating" the
637 // global series of random numbers with a new seed.
638 // It uses an algorithm that apparently used to be used in gcc rand()
639 // provided under GNU LGPL v2.1.
640 //--------------------------------------------------------------------------
641 class Rand
642 {
643 public:
644 Rand()
645 {
646 #ifdef _WIN32
647 rand_s( &m_seed );
648 #else
649 std::fstream fin( "/dev/urandom", std::ios::in );
650 if ( fin.is_open() )
651 fin.read( (char *) ( &m_seed ), sizeof ( m_seed ) );
652 else
653 {
654 fin.clear();
655 fin.open( "/dev/random", std::ios::in );
656 if ( fin.is_open() )
657 fin.read( (char *) ( &m_seed ), sizeof ( m_seed ) );
658 else
659 m_seed = 0;
660 }
661 fin.close();
662 #endif
663 }
664 Rand( unsigned int seed )
665 {
666 m_seed = seed;
667 }
668 unsigned int operator()()
669 {
670 unsigned int next = m_seed;
671 int result;
672
673 next *= 1103515245;
674 next += 12345;
675 result = (unsigned int) ( next / max ) % 2048;
676
677 next *= 1103515245;
678 next += 12345;
679 result <<= 10;
680 result ^= (unsigned int) ( next / max ) % 1024;
681
682 next *= 1103515245;
683 next += 12345;
684 result <<= 10;
685 result ^= (unsigned int) ( next / max ) % 1024;
686
687 m_seed = next;
688
689 return result;
690 }
691 static const unsigned int max = 65536;
692 private:
693 unsigned int m_seed;
694 };
695
696 void plFontToWxFontParameters( PLUNICODE fci, PLFLT scaledFontSize, wxFontFamily &family, int &style, int &weight, int &pt )
697 {
698 unsigned char plFontFamily, plFontStyle, plFontWeight;
699
700 plP_fci2hex( fci, &plFontFamily, PL_FCI_FAMILY );
701 plP_fci2hex( fci, &plFontStyle, PL_FCI_STYLE );
702 plP_fci2hex( fci, &plFontWeight, PL_FCI_WEIGHT );
703
704 family = fontFamilyLookup[plFontFamily];
705 style = fontStyleLookup[plFontStyle];
706 weight = fontWeightLookup[plFontWeight];
707 pt = ROUND( scaledFontSize );
708 }
709
710 Font::Font ( )
711 {
712 m_fci = 0;
713 m_size = std::numeric_limits<PLFLT>::quiet_NaN();
714 m_underlined = false;
715 m_hasFont = false;
716 }
717
718 Font::Font( PLUNICODE fci, PLFLT size, bool underlined, bool createFontOnConstruction )
719 {
720 m_fci = fci;
721 m_size = size;
722 m_underlined = underlined;
723 m_hasFont = false;
724 if ( createFontOnConstruction )
725 createFont();
726 }
727
728 void Font::createFont()
729 {
730 wxFontFamily family;
731 int style;
732 int weight;
733 int pt;
734 plFontToWxFontParameters( m_fci, m_size, family, style, weight, pt );
735
736 m_font = wxFont( pt, family, style, weight, m_underlined, wxEmptyString, wxFONTENCODING_DEFAULT );
737 //wxWidgets has a feature where wxDEFAULT can be passed in as the size in the constructor
738 //which gives the default size for the system. Annoyingly wxDEFAULT is 70 which can get used
739 //as an actual size. The workaround as per http://trac.wxwidgets.org/ticket/12315 is to call
740 //wxFont::SetPointSize after construction.
741 if ( pt == wxDEFAULT )
742 m_font.SetPointSize( pt );
743 m_hasFont = true;
744 }
745
746 wxFont Font::getWxFont()
747 {
748 if ( !m_hasFont )
749 createFont();
750 return m_font;
751 }
752
753 bool operator ==( const Font &lhs, const Font &rhs )
754 {
755 return lhs.getFci() == rhs.getFci()
756 && lhs.getSize() == rhs.getSize()
757 && lhs.getUnderlined() == rhs.getUnderlined();
758 }
759
760 //--------------------------------------------------------------------------
761 // FontGrabber::FontGrabber( )
762 //
763 // Default constructor
764 //--------------------------------------------------------------------------
765 FontGrabber::FontGrabber( )
766 {
767 m_lastWasCached = false;
768 }
769
770 //--------------------------------------------------------------------------
771 // Font FontGrabber::GetFont( PLUNICODE fci )
772 //
773 // Get the requested font either fresh or from the cache.
774 //--------------------------------------------------------------------------
775 Font FontGrabber::GetFont( PLUNICODE fci, PLFLT scaledFontSize, bool underlined )
776 {
777 Font newFont( fci, scaledFontSize, underlined );
778 if ( m_prevFont == newFont )
779 {
780 m_lastWasCached = true;
781 return m_prevFont;
782 }
783
784 m_lastWasCached = false;
785
786 return m_prevFont = newFont;
787 }
788
789 //--------------------------------------------------------------------------
790 // wxPLDevice::wxPLDevice( void )
791 //
792 // Constructor of the standard wxWidgets device based on the wxPLDevBase
793 // class. Only some initialisations are done.
794 //--------------------------------------------------------------------------
795 wxPLDevice::wxPLDevice( PLStream *pls, char * mfo, PLINT text, PLINT hrshsym )
796 : m_plplotEdgeLength( PLFLT( SHRT_MAX ) ), m_interactiveTextImage( 1, 1 )
797 {
798 PLPLOT_wxLogDebug( "wxPLDevice(): enter" );
799 m_fixedAspect = false;
800
801 m_lineSpacing = 1.0;
802
803 m_dc = NULL;
804
805 wxGraphicsContext *gc = wxGraphicsContext::Create( m_interactiveTextImage );
806 PLPLOT_wxLogDebug( "wxPLDevice(): gc done" );
807 try
808 {
809 m_interactiveTextGcdc = new wxGCDC( gc );
810 }
811 catch ( ... )
812 {
813 delete gc;
814 throw( "wxPLDevice::wxPLDevice: unknown failure in new wxGCDC( gc )" );
815 }
816 PLPLOT_wxLogDebug( "wxPLDevice(): m_interactiveTextGcdc done" );
817
818 if ( mfo )
819 strcpy( m_mfo, mfo );
820 else
821 //assume we will be outputting to the default
822 //memory map until we are given a dc to draw to
823 #ifdef WXPLVIEWER_DEBUG
824 strcpy( m_mfo, "plplotMemoryMap" );
825 #else
826 strcpy( m_mfo, "plplotMemoryMap??????????" );
827 #endif
828
829 // be verbose and write out debug messages
830 #ifdef _DEBUG
831 pls->verbose = 1;
832 pls->debug = 1;
833 #endif
834
835 pls->color = 1; // Is a color device
836 pls->dev_flush = 1; // Handles flushes
837 pls->dev_fill0 = 1; // Can handle solid fills
838 pls->dev_fill1 = 0; // Can't handle pattern fills
839 pls->dev_dash = 0;
840 pls->dev_clear = 1; // driver supports clear
841 pls->plbuf_write = 1; // use the plot buffer!
842 pls->termin = ( strlen( m_mfo ) ) > 0 ? 0 : 1; // interactive device unless we are writing to memory - pretty sure this is an unused option though
843 pls->graphx = GRAPHICS_MODE; // This indicates this is a graphics driver. PLplot will therefore call pltext() before outputting text, however we currently have not implemented catching that text.
844
845 if ( text )
846 {
847 pls->dev_text = 1; // want to draw text
848 pls->dev_unicode = 1; // want unicode
849 if ( hrshsym )
850 pls->dev_hrshsym = 1;
851 }
852
853
854 // Set up physical limits of plotting device in plplot internal units
855 // we just tell plplot we are the maximum plint in both dimensions
856 //which gives us the best resolution
857 plP_setphy( (PLINT) 0, (PLINT) SHRT_MAX,
858 (PLINT) 0, (PLINT) SHRT_MAX );
859
860 // set dpi and page size defaults if the user has not already set
861 // these with -dpi or -geometry command line options or with
862 // plspage.
863
864 if ( pls->xdpi <= 0. || pls->ydpi <= 0. )
865 {
866 // Use recommended default pixels per inch.
867 plspage( PLPLOT_DEFAULT_PIXELS_PER_INCH, PLPLOT_DEFAULT_PIXELS_PER_INCH, 0, 0, 0, 0 );
868 }
869
870 if ( pls->xlength == 0 || pls->ylength == 0 )
871 {
872 // Use recommended default pixel width and height.
873 plspage( 0., 0., PLPLOT_DEFAULT_WIDTH_PIXELS, PLPLOT_DEFAULT_HEIGHT_PIXELS, 0, 0 );
874 }
875 m_localBufferPosition = 0;
876
877 SetSize( pls, plsc->xlength, plsc->ylength );
878
879 if ( pls->dev_data )
880 {
881 SetDC( pls, (wxDC *) pls->dev_data );
882 PLPLOT_wxLogDebug( "wxPLDevice(): SetDC done" );
883 }
884 else
885 {
886 SetupMemoryMap();
887 }
888
889 PLPLOT_wxLogDebug( "wxPLDevice(): leave" );
890 //this must be the absolute last thing that is done
891 //so that if an exception is thrown pls->dev remains as NULL
892 pls->dev = (void *) this;
893 }
894
895 //--------------------------------------------------------------------------
896 // wxPLDevice::~wxPLDevice( void )
897 //
898 // The destructor frees memory allocated by the device.
899 //--------------------------------------------------------------------------
900 wxPLDevice::~wxPLDevice()
901 {
902 if ( m_outputMemoryMap.isValid() )
903 {
904 #ifdef PL_WXWIDGETS_IPC3
905 m_header.completeFlag = 1;
906 TransmitBuffer( NULL, transmissionComplete );
907 #else
908 MemoryMapHeader *header = (MemoryMapHeader *) ( m_outputMemoryMap.getBuffer() );
909 header->completeFlag = 1;
910 #endif
911 }
912
913 delete m_interactiveTextGcdc;
914 }
915
916 //--------------------------------------------------------------------------
917 // void wxPLDevice::PreDestructorTidy( PLStream *pls )
918 //
919 // This function performs any tidying up that requires a PLStream. should
920 // be called before the destructor obviously
921 //--------------------------------------------------------------------------
922 void wxPLDevice::PreDestructorTidy( PLStream *pls )
923 {
924 if ( !m_dc && pls->nopause )
925 TransmitBuffer( pls, transmissionClose );
926 }
927
928 //--------------------------------------------------------------------------
929 // void wxPLDevice::DrawLine( short x1a, short y1a, short x2a, short y2a )
930 //
931 // Draw a line from (x1a, y1a) to (x2a, y2a).
932 //--------------------------------------------------------------------------
933 void wxPLDevice::DrawLine( short x1a, short y1a, short x2a, short y2a )
934 {
935 if ( !m_dc )
936 return;
937
938 Clipper clipper( m_dc, GetClipRegion().GetBox() );
939 Scaler scaler( m_dc, 1.0 / m_scale, 1.0 / m_scale );
940 DrawingObjectsChanger drawingObjectsChanger( m_dc, m_pen, m_brush );
941 m_dc->DrawLine( (wxCoord) ( m_xAspect * x1a ), (wxCoord) ( m_yAspect * ( m_plplotEdgeLength - y1a ) ),
942 (wxCoord) ( m_xAspect * x2a ), (wxCoord) ( m_yAspect * ( m_plplotEdgeLength - y2a ) ) );
943 }
944
945
946 //--------------------------------------------------------------------------
947 // void wxPLDevice::DrawPolyline( short *xa, short *ya, PLINT npts )
948 //
949 // Draw a poly line - coordinates are in the xa and ya arrays.
950 //--------------------------------------------------------------------------
951 void wxPLDevice::DrawPolyline( short *xa, short *ya, PLINT npts )
952 {
953 if ( !m_dc )
954 return;
955 Clipper clipper( m_dc, GetClipRegion().GetBox() );
956 Scaler scaler( m_dc, 1.0 / m_scale, 1.0 / m_scale );
957 DrawingObjectsChanger drawingObjectsChanger( m_dc, m_pen, m_brush );
958 for ( PLINT i = 1; i < npts; i++ )
959 m_dc->DrawLine( m_xAspect * xa[i - 1], m_yAspect * ( m_plplotEdgeLength - ya[i - 1] ),
960 m_xAspect * xa[i], m_yAspect * ( m_plplotEdgeLength - ya[i] ) );
961 }
962
963
964 //--------------------------------------------------------------------------
965 // void wxPLDevice::ClearBackground( PLStream* pls, PLINT bgr, PLINT bgg, PLINT bgb,
966 // PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
967 //
968 // Clear parts ((x1,y1) to (x2,y2)) of the background in color (bgr,bgg,bgb).
969 //--------------------------------------------------------------------------
970 void wxPLDevice::ClearBackground( PLStream* pls, PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
971 {
972 if ( !m_dc )
973 return;
974
975 x1 = x1 < 0 ? 0 : x1;
976 x2 = x2 < 0 ? m_plplotEdgeLength : x2;
977 y1 = y1 < 0 ? 0 : y1;
978 y2 = y2 < 0 ? m_plplotEdgeLength : y2;
979
980 PLINT x = MIN( x1, x2 ) * m_xAspect;
981 PLINT y = ( m_plplotEdgeLength - MAX( y1, y2 ) ) * m_yAspect;
982 PLINT width = abs( x1 - x2 ) * m_xAspect;
983 PLINT height = abs( y1 - y2 ) * m_yAspect;
984
985 if ( width > 0 && height > 0 )
986 {
987 PLINT r, g, b;
988 PLFLT a;
989 plgcolbga( &r, &g, &b, &a );
990 wxColour bgColour( r, g, b, a * 255 );
991 DrawingObjectsChanger changer( m_dc, wxPen( bgColour, 0 ), wxBrush( bgColour ) );
992 Scaler scaler( m_dc, 1.0 / m_scale, 1.0 / m_scale );
993 m_dc->DrawRectangle( x, y, width, height );
994 }
995 }
996
997
998 //--------------------------------------------------------------------------
999 // void wxPLDevice::FillPolygon( PLStream *pls )
1000 //
1001 // Draw a filled polygon.
1002 //--------------------------------------------------------------------------
1003 void wxPLDevice::FillPolygon( PLStream *pls )
1004 {
1005 if ( !m_dc )
1006 return;
1007
1008 //edge the polygon with a 0.5 pixel line to avoid seams. This is a
1009 //bit of a bodge really but this is a difficult problem
1010 wxPen edgePen( m_brush.GetColour(), m_scale, wxSOLID );
1011 DrawingObjectsChanger changer( m_dc, edgePen, m_brush );
1012 //DrawingObjectsChanger changer(m_dc, wxNullPen, m_brush );
1013 Clipper clipper( m_dc, GetClipRegion().GetBox() );
1014 Scaler scaler( m_dc, 1.0 / m_scale, 1.0 / m_scale );
1015 wxPoint *points = new wxPoint[pls->dev_npts];
1016 wxCoord xoffset = 0;
1017 wxCoord yoffset = 0;
1018
1019 for ( int i = 0; i < pls->dev_npts; i++ )
1020 {
1021 points[i].x = (int) ( m_xAspect * pls->dev_x[i] );
1022 points[i].y = (int) ( m_yAspect * ( m_plplotEdgeLength - pls->dev_y[i] ) );
1023 }
1024
1025 if ( pls->dev_eofill )
1026 {
1027 m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxODDEVEN_RULE );
1028 }
1029 else
1030 {
1031 m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxWINDING_RULE );
1032 }
1033 delete[] points;
1034 }
1035
1036
1037 //--------------------------------------------------------------------------
1038 // void wxPLDevice::SetWidth( PLStream *pls )
1039 //
1040 // Set the width of the drawing pen.
1041 //--------------------------------------------------------------------------
1042 void wxPLDevice::SetWidth( PLStream *pls )
1043 {
1044 PLFLT width = ( pls->width > 0.0 ? pls->width : 1.0 ) * m_scale;
1045 m_pen = wxPen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b,
1046 pls->curcolor.a * 255 ), width, wxSOLID );
1047 }
1048
1049
1050 //--------------------------------------------------------------------------
1051 // void wxPLDevice::SetColor( PLStream *pls )
1052 //
1053 // Set color from PLStream.
1054 //--------------------------------------------------------------------------
1055 void wxPLDevice::SetColor( PLStream *pls )
1056 {
1057 PLFLT width = ( pls->width > 0.0 ? pls->width : 1.0 ) * m_scale;
1058 m_pen = wxPen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b,
1059 pls->curcolor.a * 255 ), width, wxSOLID );
1060 m_brush = wxBrush( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b,
1061 pls->curcolor.a * 255 ) );
1062 }
1063
1064 //--------------------------------------------------------------------------
1065 // void wxPLDevice::SetXorMode( bool on )
1066 //
1067 // Set whether we want XOR mode on or off.
1068 //--------------------------------------------------------------------------
1069 void wxPLDevice::SetXorMode( bool on )
1070 {
1071 if ( m_dc )
1072 m_dc->SetLogicalFunction( on ? wxXOR : wxCOPY );
1073 }
1074
1075 //--------------------------------------------------------------------------
1076 // void wxPLDevice::SetDC( PLStream *pls, void* dc )
1077 //
1078 // Adds a dc to the device. In that case, the drivers doesn't provide
1079 // a GUI.
1080 //--------------------------------------------------------------------------
1081 void wxPLDevice::SetDC( PLStream *pls, wxDC* dc )
1082 {
1083 if ( m_outputMemoryMap.isValid() )
1084 throw( "wxPLDevice::SetDC The DC must be set before initialisation. The device is outputting to a separate viewer" );
1085 m_dc = dc; // Add the dc to the device
1086 m_useDcTextTransform = false;
1087 m_gc = NULL;
1088 if ( m_dc )
1089 {
1090 #if wxVERSION_NUMBER >= 2902
1091 m_useDcTextTransform = m_dc->CanUseTransformMatrix();
1092 #endif
1093 //Prior to some point in wxWidgets 3.1 development wxGCDC didn't
1094 //support transformation matrices, but the underlying
1095 //wxGraphicsContext had its own transformation matrix ability.
1096 //So check if we are using a wxGCDC using RTTI and if so we can
1097 //use this.
1098 wxGCDC *gcdc = NULL;
1099 try
1100 {
1101 //put this in a try block as I'm not sure if it will throw if
1102 //RTTI is switched off
1103 gcdc = dynamic_cast< wxGCDC* >( m_dc );
1104 }
1105 catch ( ... )
1106 {
1107 throw( "unknown failure in dynamic_cast< wxGCDC* >( m_dc )" );
1108 }
1109 if ( gcdc )
1110 m_gc = gcdc->GetGraphicsContext();
1111
1112 strcpy( m_mfo, "" );
1113 SetSize( pls, m_width, m_height ); //call with our current size to set the scaling
1114 pls->has_string_length = 1; // Driver supports string length calculations, if we have a dc to draw on
1115 }
1116 else
1117 {
1118 pls->has_string_length = 0; //if we have no device to draw on we cannot check string size
1119 }
1120 }
1121
1122 // This function will draw a section of text given by section at location
1123 // x, y relative to the origin xOrigin, yOrigin. The text must not
1124 // contain any newline characters or PLplot escapes.
1125 // transform is a transformation to be applied to the device context AFTER
1126 // the origin of the device context has been moved to xOrigin, yOrigin. The
1127 // purpose of having this origin is to allow the units used by wxWidgets to
1128 // be different to those passed in and for the scaling factors to be
1129 // different in each direction.
1130 // scaledFontSize is the font size in pt after any scaling for super/sub script.
1131 // The underlined flag, overlined flag, fci and text colours are inputs defining
1132 // the text style.
1133 // On return yScale, textWidth, textHeigth and textDepth will be
1134 // filled with the scaling value used for the Y dimension and the
1135 // (positive) width, (positive) ascender height and (positive)
1136 // descender depth of the text string.
1137 // If drawText is true the text will actually be rendered. If it is false the size
1138 // will be calculated but the text will not be rendered.
1139 //--------------------------------------------------------------------------
1140 void wxPLDevice::DrawTextSection( wxString section, wxCoord xOrigin, wxCoord yOrigin, wxCoord x, wxCoord y, PLFLT *transform, PLFLT scaledFontSize, bool drawText, bool underlined, PLUNICODE fci, unsigned char red, unsigned char green, unsigned char blue, PLFLT alpha, PLFLT &yScale, wxCoord &sectionWidth, wxCoord &sectionHeight, wxCoord &sectionDepth )
1141 {
1142 //for text, work in native coordinates, because it is significantly easier when
1143 //dealing with superscripts and text chunks.
1144 //The scaler object sets the scale to the new value until it is destroyed
1145 //when this function exits.
1146 Scaler scaler( m_dc, 1.0, 1.0 );
1147 //Also move the origin back to the top left, rather than the bottom
1148 OriginChanger originChanger( m_dc, 0, wxCoord( m_height - m_plplotEdgeLength / m_yScale ) );
1149 //save the text state for automatic restoration on scope exit
1150 TextObjectsSaver textObjectsSaver( m_dc );
1151
1152 wxCoord leading;
1153 Font font = m_fontGrabber.GetFont( fci, scaledFontSize, underlined );
1154
1155 // Adjusted so that utf8 "heavy multiplication x", "number sign",
1156 // "four teardrop-spoked asterisk", and "8-spoked asterisk" are
1157 // aligned properly when running
1158 //
1159 // python (or python3 as appropriate) examples/python/test_circle.py -dev wxwidgets
1160 //
1161 PLFLT empiricalYOffset = -0.020 * scaledFontSize * m_yScale;
1162 wxCoord empiricalY = y + empiricalYOffset;
1163 // Return via the yScale argument the value used for scaling in the Y direction.
1164 yScale = m_yScale;
1165 if ( m_dc )
1166 {
1167 wxFont theFont = font.getWxFont();
1168
1169 // gdb sessions typically show something like the following:
1170 // 4: sectionWidth = (wxCoord &) @0x7fffffffd6ec: 7
1171 // 3: sectionHeight = (wxCoord &) @0x7fffffffd6e8: 13
1172 // 2: sectionDepth = (wxCoord &) @0x7fffffffd6e4: 3
1173 // 1: leading = 0
1174 // That is, sectionWidth, sectionHeight, and sectionDepth
1175 // returned by GetTextExtent are all normally small positive integers while leading
1176 // returned by the same call is typically zero.
1177 m_dc->GetTextExtent( section, &sectionWidth, &sectionHeight,
1178 &sectionDepth, &leading, &theFont );
1179 }
1180 else
1181 {
1182 wxFont theFont = font.getWxFont();
1183 // See comments above concerning interpretation of GetTextExtent results.
1184 m_interactiveTextGcdc->GetTextExtent( section, &sectionWidth, &sectionHeight,
1185 &sectionDepth, &leading, &theFont );
1186 }
1187
1188 // The leading value that is returned is a vertical offset used by
1189 // some font designers, but I (AWI) can find no documentation
1190 // concerning the sign convention for leading so I simply follow
1191 // here the convention previously used by this code.
1192 // Note, that all fonts I have tried have zero leading so (a) this
1193 // adopted sign convention does not matter for them, and (b) if it
1194 // is wrong here, there is no chance to debug it by looking at the
1195 // vertical offset of rendered strings.
1196 sectionHeight -= leading;
1197 sectionDepth += leading;
1198 sectionWidth *= m_xScale;
1199 sectionHeight *= m_yScale;
1200 sectionDepth *= m_yScale;
1201
1202 // Draw the text if requested
1203 if ( drawText && m_dc )
1204 {
1205 //set the text colour
1206 m_dc->SetTextBackground( wxColour( red, green, blue, alpha * 255 ) );
1207 m_dc->SetTextForeground( wxColour( red, green, blue, alpha * 255 ) );
1208
1209 // Set the clipping limits
1210 PLINT rcx[4], rcy[4];
1211 difilt_clip( rcx, rcy );
1212 wxPoint cpoints[4];
1213 for ( int i = 0; i < 4; i++ )
1214 {
1215 cpoints[i].x = rcx[i] / m_xScale;
1216 cpoints[i].y = m_height - rcy[i] / m_yScale;
1217 }
1218 Clipper clipper( m_dc, wxRegion( 4, cpoints ).GetBox() );
1219
1220 Font font = m_fontGrabber.GetFont( fci, scaledFontSize, underlined );
1221 m_dc->SetFont( font.getWxFont() );
1222
1223 if ( m_useDcTextTransform )
1224 {
1225 #if wxVERSION_NUMBER >= 2902
1226 wxAffineMatrix2D originalDcMatrix = m_dc->GetTransformMatrix();
1227
1228 wxAffineMatrix2D newMatrix = originalDcMatrix;
1229 newMatrix.Translate( xOrigin / m_xScale, m_height - yOrigin / m_yScale );
1230 wxAffineMatrix2D textMatrix;
1231 // For some reason we don't do the mirroring like in the
1232 // wxGraphicsContext when we use a wxDC.
1233 PLFLT xTransform = transform[4] / m_xScale;
1234 PLFLT yTransform = transform[5] / m_yScale;
1235 textMatrix.Set(
1236 wxMatrix2D(
1237 transform[0], transform[2],
1238 transform[1], transform[3] ),
1239 wxPoint2DDouble(
1240 xTransform, yTransform ) );
1241 newMatrix.Concat( textMatrix );
1242 m_dc->SetTransformMatrix( newMatrix );
1243
1244 m_dc->DrawText( section, x / m_xScale, -empiricalY / m_yScale );
1245
1246 m_dc->SetTransformMatrix( originalDcMatrix );
1247 #endif
1248 }
1249 else if ( m_gc )
1250 {
1251 wxGraphicsMatrix originalGcMatrix = m_gc->GetTransform();
1252
1253 m_gc->Translate( xOrigin / m_xScale, m_height - yOrigin / m_yScale ); //move to text starting position
1254 //Create a wxGraphicsMatrix from our plplot transformation matrix.
1255 //Note the different conventions
1256 //1) plplot transforms use notation x' = Mx, where x and x' are column vectors,
1257 // wxGraphicsContext uses xM = x' where x and x' are row vectors. This means
1258 // we must transpose the matrix.
1259 //2) plplot Affine matrices a represented by 6 values which start at the top left
1260 // and work down each column. The 3rd row is implied as 0 0 1. wxWidget matrices
1261 // are represented by 6 values which start at the top left and work along each
1262 // row. The 3rd column is implied as 0 0 1. This means we must transpose the
1263 // matrix.
1264 //3) Items 1 and 2 cancel out so we don't actually need to do anything about them.
1265 //4) The wxGraphicsContext has positive y in the downward direction, but plplot
1266 // has positive y in the upwards direction. This means we must do a reflection
1267 // in the y direction before and after applying the transform. Also we must scale
1268 // the translation parts to match the pixel scale.
1269 //The overall transform is
1270 //
1271 // |1 0 0| |transform[0] transform[2] transform[4]/m_xScale| |1 0 0|
1272 // |0 -1 0| |transform[1] transform[3] transform[5]/m_yScale| |0 -1 0|
1273 // |0 0 1| | 0 0 1 | |0 0 1|
1274 //
1275 //which results in
1276 //
1277 // | transform[0] -transform[2] 0|
1278 // |-transform[1] transform[3] 0|
1279 // | transform[4]/m_xScale -transform[5]/m_yScale 1|
1280 //
1281 PLFLT xTransform = transform[4] / m_xScale;
1282 PLFLT yTransform = transform[5] / m_yScale;
1283 wxGraphicsMatrix matrix = m_gc->CreateMatrix(
1284 transform[0], -transform[1],
1285 -transform[2], transform[3],
1286 xTransform, -yTransform );
1287 wxGraphicsMatrix reflectMatrix = m_gc->CreateMatrix();
1288 m_gc->ConcatTransform( matrix );
1289 m_gc->DrawText( section, x / m_xScale, -empiricalY / m_yScale );
1290 m_gc->SetTransform( originalGcMatrix );
1291 }
1292 else
1293 {
1294 // If we are stuck with a wxDC that has no transformation
1295 // abilities then all we can really do is rotate the text
1296 // - this is a bit of a poor state really, but to be
1297 // honest it is better than defaulting to Hershey for all
1298 // text
1299 PLFLT xTransformed = x / m_xScale * transform[0] + empiricalY / m_yScale * transform[2] + transform[4] / m_xScale;
1300 PLFLT yTransformed = x / m_xScale * transform[1] + empiricalY / m_yScale * transform[3] + transform[4] / m_xScale;
1301 // This angle calculation comes from transforming the
1302 // point (0,0) and any other point on the empiricalY = 0 line and
1303 // getting the angle from the horizontal of that line.
1304 PLFLT angle = atan2( transform[1], transform[0] ) * 180.0 / M_PI;
1305 m_dc->DrawRotatedText( section, xOrigin / m_xScale + xTransformed, m_height - yOrigin / m_yScale - yTransformed, angle );
1306 }
1307 }
1308 }
1309
1310 //--------------------------------------------------------------------------
1311 // void wxPLDevice::EndPage( PLStream* pls )
1312 // End the page. This is the point that we write the buffer to the memory
1313 // mapped file if needed
1314 //--------------------------------------------------------------------------
1315 void wxPLDevice::EndPage( PLStream* pls )
1316 {
1317 if ( !m_dc )
1318 {
1319 if ( pls->nopause )
1320 TransmitBuffer( pls, transmissionEndOfPageNoPause );
1321 else
1322 TransmitBuffer( pls, transmissionEndOfPage );
1323 return;
1324 }
1325 }
1326
1327 //--------------------------------------------------------------------------
1328 // void wxPLDevice::BeginPage( PLStream* pls )
1329 // Sets up for transfer in case it is needed and sets the current state
1330 //--------------------------------------------------------------------------
1331 void wxPLDevice::BeginPage( PLStream* pls )
1332 {
1333 if ( !m_dc )
1334 {
1335 m_localBufferPosition = 0;
1336 TransmitBuffer( NULL, transmissionBeginPage );
1337 }
1338
1339 // Get the starting colour, width and font from the stream
1340 SetWidth( pls );
1341 SetColor( pls );
1342
1343 //clear the page
1344 ClearBackground( pls );
1345 }
1346
1347 //--------------------------------------------------------------------------
1348 // void wxPLDevice::SetSize( PLStream* pls )
1349 // Set the size of the page, scale parameters and the dpi
1350 //--------------------------------------------------------------------------
1351 void wxPLDevice::SetSize( PLStream* pls, int width, int height )
1352 {
1353 //we call BeginPage, before we fiddle with fixed aspect so that the
1354 //whole background gets filled
1355 // get boundary coordinates in plplot units
1356 PLINT xmin;
1357 PLINT xmax;
1358 PLINT ymin;
1359 PLINT ymax;
1360 plP_gphy( &xmin, &xmax, &ymin, &ymax );
1361 //split the scaling into an overall scale, the same in both dimensions
1362 //and an aspect part which differs in both directions.
1363 //We will apply the aspect ratio part, and let the DC do the overall
1364 //scaling. This gives us subpixel accuracy, but ensures line thickness
1365 //remains consistent in both directions
1366 m_xScale = width > 0 ? (PLFLT) ( xmax - xmin ) / (PLFLT) width : 0.0;
1367 m_yScale = height > 0 ? (PLFLT) ( ymax - ymin ) / (PLFLT) height : 0.0;
1368 m_scale = MIN( m_xScale, m_yScale );
1369
1370 if ( !m_fixedAspect )
1371 {
1372 m_xAspect = m_scale / m_xScale;
1373 m_yAspect = m_scale / m_yScale;
1374 }
1375 else
1376 {
1377 //now sort out the fixed aspect and reset the logical scale if needed
1378 if ( PLFLT( height ) / PLFLT( width ) > m_yAspect / m_xAspect )
1379 {
1380 m_scale = m_xScale * m_xAspect;
1381 m_yScale = m_scale / m_yAspect;
1382 }
1383 else
1384 {
1385 m_scale = m_yScale * m_yAspect;
1386 m_xScale = m_scale / m_xAspect;
1387 }
1388 }
1389
1390 m_width = ( xmax - xmin ) / m_xScale;
1391 pls->xlength = PLINT( m_width + 0.5 );
1392 m_height = ( ymax - ymin ) / m_yScale;
1393 pls->ylength = PLINT( m_height + 0.5 );
1394
1395 // Set the number of plplot pixels per mm
1396 plP_setpxl( m_plplotEdgeLength / m_width * pls->xdpi / PLPLOT_MM_PER_INCH, m_plplotEdgeLength / m_height * pls->ydpi / PLPLOT_MM_PER_INCH );
1397 //
1398 //The line above is technically correct, however, 3d text only looks at device dimensions (32767x32767 square)
1399 //but 2d rotated text uses the mm size derived above. The only way to consistently deal with them is
1400 //by having an equal device units per mm in both directions and do a correction in DrawText().
1401 //Usefully this also allows us to change text rotation as aspect ratios change
1402 //PLFLT size = m_xAspect > m_yAspect ? m_width : m_height;
1403 //plP_setpxl( m_plplotEdgeLength / size * pls->xdpi / PLPLOT_MM_PER_INCH, m_plplotEdgeLength / size * pls->ydpi / PLPLOT_MM_PER_INCH );
1404
1405
1406 // redraw the plot
1407 if ( m_dc && pls->plbuf_buffer )
1408 plreplot();
1409 }
1410
1411
1412 void wxPLDevice::FixAspectRatio( bool fix )
1413 {
1414 m_fixedAspect = fix;
1415 }
1416
1417 void wxPLDevice::Flush( PLStream *pls )
1418 {
1419 if ( !m_dc )
1420 #ifdef PL_WXWIDGETS_IPC3
1421 TransmitBuffer( pls, transmissionFlush );
1422 #else
1423 TransmitBuffer( pls, transmissionComplete );
1424 #endif
1425 }
1426
1427 // This function transmits data to the gui program via a memory map.
1428 // This function can be called with pls set to NULL for transmission
1429 // of just a flag for e.g. page end or begin.
1430 void wxPLDevice::TransmitBuffer( PLStream* pls, unsigned char transmissionType )
1431 {
1432 if ( !m_outputMemoryMap.isValid() )
1433 return;
1434 #ifdef PL_WXWIDGETS_IPC3
1435 // New much cleaner variant of this code which makes use of two
1436 // additional members of the MemoryMapHeader called transmissionType
1437 // and plbufAmountToTransmit which contain what their names imply.
1438
1439 try
1440 {
1441 m_header.transmissionType = transmissionType;
1442 // This value may be zeroed below for those transmissionTypes which require
1443 // that no part of plbuf should be transmitted.
1444 m_header.plbufAmountToTransmit = pls ? pls->plbuf_top - m_localBufferPosition : 0;
1445
1446 switch ( transmissionType )
1447 {
1448 // Special valid cases.
1449 case transmissionLocate:
1450 m_header.locateModeFlag = 1;
1451 break;
1452 // N.B. These transmissionTypes require
1453 // that no part of plbuf should be transmitted.
1454 case transmissionRequestTextSize:
1455 case transmissionClose:
1456 m_header.plbufAmountToTransmit = 0;
1457 break;
1458 // Generic valid cases where nothing special has to be done
1459 case transmissionBeginPage:
1460 case transmissionEndOfPage:
1461 case transmissionEndOfPageNoPause:
1462 case transmissionComplete:
1463 case transmissionFlush:
1464 break;
1465
1466 // Invalid cases.
1467 default:
1468 throw( "wxPLDevice::TransmitBuffer: called with invalid value of transmissionType" );
1469 break;
1470 }
1471
1472 #ifdef PLPLOT_WX_DEBUG_OUTPUT
1473 std::cerr << "Before transmitBytes" << std::endl;
1474 std::cerr << "transmissionType = " << static_cast<unsigned int>( m_header.transmissionType ) << std::endl;
1475 std::cerr << "plbufAmountToTransmit = " << m_header.plbufAmountToTransmit << std::endl;
1476 std::cerr << "viewerOpenFlag = " << m_header.viewerOpenFlag << std::endl;
1477 std::cerr << "locateModeFlag = " << m_header.locateModeFlag << std::endl;
1478 std::cerr << "completeFlag = " << m_header.completeFlag << std::endl;
1479 #endif // #ifdef PLPLOT_WX_DEBUG_OUTPUT
1480 m_outputMemoryMap.transmitBytes( true, &m_header, sizeof ( MemoryMapHeader ) );
1481 if ( m_header.plbufAmountToTransmit > 0 )
1482 {
1483 // N.B. the above condition implies pls is non-NULL.
1484 // Transmit m_header.plbufAmountToTransmit bytes of plbuf to the reader process.
1485 m_outputMemoryMap.transmitBytes( false, (char *) pls->plbuf_buffer + m_localBufferPosition, m_header.plbufAmountToTransmit );
1486 m_localBufferPosition += m_header.plbufAmountToTransmit;
1487 }
1488 } // End of try block
1489
1490
1491 catch ( const char *message )
1492 {
1493 plwarn( message );
1494 plwarn( "wxPLDevice::TransmitBuffer: error" );
1495 }
1496
1497 catch ( ... )
1498 {
1499 plwarn( "wxPLDevice::TransmitBuffer: Unknown error" );
1500 }
1501
1502 #else // #ifdef PL_WXWIDGETS_IPC3
1503 // Amount of plbuf buffer to copy.
1504 size_t amountToCopy = pls ? pls->plbuf_top - m_localBufferPosition : 0;
1505 const size_t headerSize = sizeof ( transmissionType ) + sizeof ( size_t );
1506 bool first = true;
1507 size_t counter = 0;
1508 const size_t counterLimit = 10000;
1509 bool completed = false;
1510 while ( !completed && counter < counterLimit )
1511 {
1512 //if we are doing multiple loops then pause briefly before we
1513 //lock to give the reading application a chance to spot the
1514 //change.
1515 if ( !first )
1516 wxMilliSleep( 10 );
1517 first = false;
1518
1519 size_t copyAmount = 0;
1520 size_t freeSpace = 0;
1521 //lock the mutex so reading and writing don't overlap
1522 try
1523 {
1524 //PLNamedMutexLocker lock( &m_mutex );
1525 MemoryMapHeader & mapHeader = *(MemoryMapHeader *) m_outputMemoryMap.getBuffer();
1526
1527 //check how much free space we have before the end of the buffer
1528 //or if we have looped round how much free space we have before
1529 //we reach the read point
1530 freeSpace = m_outputMemoryMap.getSize() - mapHeader.writeLocation;
1531 // if readLocation is at the beginning then don't quite fill up the buffer
1532 if ( mapHeader.readLocation == plMemoryMapReservedSpace )
1533 --freeSpace;
1534
1535 //if the free space left in the file is less than that needed for the header then
1536 //just tell the GUI to skip the rest of the file so it can start again at the
1537 //beginning of the file.
1538 if ( freeSpace <= headerSize )
1539 {
1540 if ( mapHeader.readLocation > mapHeader.writeLocation ) //don't overtake the read buffer
1541 freeSpace = 0;
1542 else if ( mapHeader.readLocation == plMemoryMapReservedSpace ) // don't catch up exactly with the read buffer
1543 freeSpace = 0;
1544 else
1545 {
1546 //send a skip end of file command and move back to the beginning of the file
1547 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1548 (void *) ( &transmissionSkipFileEnd ), sizeof ( transmissionSkipFileEnd ) );
1549 mapHeader.writeLocation = plMemoryMapReservedSpace;
1550 counter = 0;
1551 plwarn( "wxWidgets wrapping buffer" );
1552 continue;
1553 }
1554 }
1555
1556 //if this is a beginning of page, then send a beginning of page flag first
1557 if ( transmissionType == transmissionBeginPage )
1558 {
1559 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1560 (void *) ( &transmissionBeginPage ), sizeof ( transmissionBeginPage ) );
1561 mapHeader.writeLocation += sizeof ( transmissionBeginPage );
1562 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1563 mapHeader.writeLocation = plMemoryMapReservedSpace;
1564 counter = 0;
1565 if ( amountToCopy == 0 )
1566 completed = true;
1567 transmissionType = transmissionRegular;
1568 continue;
1569 }
1570
1571 //if this is a end of page and we have completed
1572 //the buffer then send a end of page flag first
1573 if ( ( transmissionType == transmissionEndOfPage || transmissionType == transmissionEndOfPageNoPause )
1574 && amountToCopy == 0 )
1575 {
1576 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1577 (void *) ( &transmissionType ), sizeof ( transmissionType ) );
1578 mapHeader.writeLocation += sizeof ( transmissionType );
1579 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1580 mapHeader.writeLocation = plMemoryMapReservedSpace;
1581 counter = 0;
1582 completed = true;
1583 continue;
1584 }
1585
1586 if ( transmissionType == transmissionLocate && amountToCopy == 0 )
1587 {
1588 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1589 (void *) ( &transmissionLocate ), sizeof ( transmissionLocate ) );
1590 mapHeader.writeLocation += sizeof ( transmissionLocate );
1591 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1592 mapHeader.writeLocation = plMemoryMapReservedSpace;
1593 mapHeader.locateModeFlag = 1;
1594 counter = 0;
1595 completed = true;
1596 continue;
1597 }
1598
1599 if ( transmissionType == transmissionRequestTextSize )
1600 {
1601 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1602 (void *) ( &transmissionRequestTextSize ), sizeof ( transmissionRequestTextSize ) );
1603 mapHeader.writeLocation += sizeof ( transmissionRequestTextSize );
1604 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1605 mapHeader.writeLocation = plMemoryMapReservedSpace;
1606 counter = 0;
1607 completed = true;
1608 continue;
1609 }
1610 if ( transmissionType == transmissionClose )
1611 {
1612 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1613 (void *) ( &transmissionType ), sizeof ( transmissionType ) );
1614 mapHeader.writeLocation += sizeof ( transmissionType );
1615 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1616 mapHeader.writeLocation = plMemoryMapReservedSpace;
1617 counter = 0;
1618 completed = true;
1619 continue;
1620 }
1621
1622 //if we have looped round stay 1 character behind the read buffer - it makes it
1623 //easier to test whether the reading has caught up with the writing or vice versa
1624 if ( mapHeader.writeLocation < mapHeader.readLocation && mapHeader.readLocation > 0 )
1625 freeSpace = mapHeader.readLocation - mapHeader.writeLocation - 1;
1626
1627 if ( freeSpace > headerSize )
1628 {
1629 //decide exactly how much to copy
1630 copyAmount = MIN( amountToCopy, freeSpace - headerSize );
1631
1632 //copy the header and the amount we can to the buffer
1633 if ( copyAmount != amountToCopy )
1634 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1635 (char *) ( &transmissionPartial ), sizeof ( transmissionPartial ) );
1636 else
1637 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation,
1638 (char *) ( &transmissionComplete ), sizeof ( transmissionComplete ) );
1639 if ( pls )
1640 {
1641 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation + sizeof ( transmissionComplete ),
1642 (char *) ( &copyAmount ), sizeof ( copyAmount ) );
1643 memcpy( m_outputMemoryMap.getBuffer() + mapHeader.writeLocation + headerSize,
1644 (char *) pls->plbuf_buffer + m_localBufferPosition, copyAmount );
1645 m_localBufferPosition += copyAmount;
1646 mapHeader.writeLocation += copyAmount + headerSize;
1647 if ( mapHeader.writeLocation == m_outputMemoryMap.getSize() )
1648 mapHeader.writeLocation = plMemoryMapReservedSpace;
1649 amountToCopy -= copyAmount;
1650 counter = 0;
1651 }
1652 if ( amountToCopy == 0 && transmissionType != transmissionEndOfPage
1653 && transmissionType != transmissionLocate
1654 && transmissionType != transmissionEndOfPageNoPause )
1655 completed = true;
1656 }
1657 else
1658 {
1659 ++counter;
1660 }
1661 }
1662 #ifdef _WIN32
1663 catch ( DWORD )
1664 {
1665 plwarn( "Locking mutex failed when trying to communicate with " NAME_wxPLViewer "." );
1666 break;
1667 }
1668 #endif
1669 catch ( ... )
1670 {
1671 plwarn( "Unknown error when trying to communicate with " NAME_wxPLViewer "." );
1672 break;
1673 }
1674 }
1675 if ( counter == counterLimit )
1676 {
1677 plwarn( "Communication timeout with " NAME_wxPLViewer " - disconnecting" );
1678 m_outputMemoryMap.close();
1679 }
1680 #endif // #ifdef PL_WXWIDGETS_IPC3
1681 }
1682
1683 void wxPLDevice::SetupMemoryMap()
1684 {
1685 PLPLOT_wxLogDebug( "SetupMemoryMap(): enter" );
1686 if ( strlen( m_mfo ) > 0 )
1687 {
1688 #ifdef PL_WXWIDGETS_IPC3
1689 const size_t mapSize = sizeof ( shmbuf );
1690 #else
1691 const size_t mapSize = 1024 * 1024;
1692 char mutexName[PLPLOT_MAX_PATH];
1693 #endif
1694 //create a memory map to hold the data and add it to the array of maps
1695 int nTries = 0;
1696 char mapName[PLPLOT_MAX_PATH];
1697 static Rand randomGenerator; // make this static so that rapid repeat calls don't use the same seed
1698 while ( nTries < 10 )
1699 {
1700 PLPLOT_wxLogDebug( "SetupMemoryMap(): mapName start" );
1701 for ( int i = 0; i < strlen( m_mfo ); ++i )
1702 {
1703 if ( m_mfo[i] == '?' )
1704 mapName[i] = 'A' + (char) ( randomGenerator() % 26 );
1705 else
1706 mapName[i] = m_mfo[i];
1707 }
1708 PLPLOT_wxLogDebug( "SetupMemoryMap(): mapName done" );
1709 mapName[strlen( m_mfo )] = '\0';
1710 //truncate it earlier if needed
1711 if ( strlen( m_mfo ) > PLPLOT_MAX_PATH - 4 )
1712 mapName[PLPLOT_MAX_PATH - 4] = '\0';
1713 pldebug( "wxPLDevice::SetupMemoryMap", "nTries = %d, mapName = %s\n", nTries, mapName );
1714 PLPLOT_wxLogDebug( "SetupMemoryMap(): m_outputMemoryMap.create call" );
1715 m_outputMemoryMap.create( mapName, mapSize, false, true );
1716 PLPLOT_wxLogDebug( "SetupMemoryMap(): m_outputMemoryMap.create done" );
1717 if ( m_outputMemoryMap.isValid() )
1718 {
1719 #ifndef PL_WXWIDGETS_IPC3
1720 strcpy( mutexName, mapName );
1721 strcat( mutexName, "mut" );
1722 pldebug( "wxPLDevice::SetupMemoryMap", "nTries = %d, mutexName = %s\n", nTries, mutexName );
1723 m_mutex.create( mutexName );
1724 if ( !m_mutex.isValid() )
1725 m_outputMemoryMap.close();
1726 #endif // #ifndef PL_WXWIDGETS_IPC3
1727 }
1728 if ( m_outputMemoryMap.isValid() )
1729 break;
1730 ++nTries;
1731 }
1732 //m_outputMemoryMap.create( m_mfo, pls->plbuf_top, false, true );
1733 //check the memory map is valid
1734 if ( !m_outputMemoryMap.isValid() )
1735 {
1736 plwarn( "Error creating memory map for wxWidget instruction transmission. The plots will not be displayed" );
1737 return;
1738 }
1739
1740 #ifdef PL_WXWIDGETS_IPC3
1741 // Should only be executed once per valid Memory map before wxPLViewer is launched.
1742 m_outputMemoryMap.initializeSemaphoresToValid( mapName );
1743 //zero out the reserved area
1744 m_header.viewerOpenFlag = 0;
1745 m_header.locateModeFlag = 0;
1746 m_header.completeFlag = 0;
1747 #else // #ifdef PL_WXWIDGETS_IPC3
1748 MemoryMapHeader *header = (MemoryMapHeader *) ( m_outputMemoryMap.getBuffer() );
1749 header->readLocation = plMemoryMapReservedSpace;
1750 header->writeLocation = plMemoryMapReservedSpace;
1751 header->viewerOpenFlag = 0;
1752 header->locateModeFlag = 0;
1753 header->completeFlag = 0;
1754 #endif // #ifdef PL_WXWIDGETS_IPC3
1755
1756 //try to find the wxPLViewer executable, in the first instance just assume it
1757 //is in the path.
1758 //wxString exeName = wxT( "/nfs/see-fs-02_users/earpros/usr/src/plplot-plplot/build/utils/" NAME_wxPLViewer );
1759 wxString exeName = wxT( NAME_wxPLViewer );
1760 if ( plInBuildTree() )
1761 {
1762 //if we are in the build tree check for the needed exe in there
1763 wxArrayString files;
1764 wxString utilsDir = wxString( wxT( BUILD_DIR ) ) + wxString( wxT( "/utils" ) );
1765 wxDir::GetAllFiles( utilsDir, &files, exeName, wxDIR_FILES | wxDIR_DIRS );
1766 if ( files.size() == 0 )
1767 wxDir::GetAllFiles( utilsDir, &files, exeName + wxT( ".exe" ), wxDIR_FILES | wxDIR_DIRS );
1768 if ( files.size() > 0 )
1769 exeName = files[0];
1770 }
1771 else
1772 {
1773 //check the plplot bin install directory
1774 wxArrayString files;
1775 wxDir::GetAllFiles( wxT( BIN_DIR ), &files, exeName, wxDIR_FILES | wxDIR_DIRS );
1776 if ( files.size() == 0 )
1777 wxDir::GetAllFiles( wxT( BIN_DIR ), &files, exeName + wxT( ".exe" ), wxDIR_FILES | wxDIR_DIRS );
1778 if ( files.size() > 0 )
1779 exeName = files[0];
1780 }
1781 //Run the wxPlViewer with command line parameters telling it the location and size of the buffer
1782 wxString command;
1783 command << wxT( "\"" ) << exeName << wxT( "\" " ) << wxString( mapName, wxConvUTF8 ) << wxT( " " ) <<
1784 mapSize << wxT( " " ) << m_width << wxT( " " ) << m_height;
1785 #ifndef WXPLVIEWER_DEBUG
1786 #ifdef _WIN32
1787
1788 if ( wxExecute( command, wxEXEC_ASYNC ) == 0 )
1789 plwarn( "Failed to run " NAME_wxPLViewer " - no plots will be shown" );
1790 #else //_WIN32
1791 //Linux doesn't like using wxExecute without a wxApp, so use system instead
1792 command << wxT( " &" );
1793 system( command.mb_str() );
1794 #endif //_WIN32
1795 #else // ifndef WXPLVIEWER_DEBUG
1796 wxString runMessage;
1797 runMessage << "Begin Running " NAME_wxPLViewer " in the debugger now to continue. Use the parameters: plplotMemoryMap " <<
1798 mapSize << " " << m_width << " " << m_height;
1799 // fprintf( stdout, runMessage );
1800 // FIXME: The above fprintf does not output runMessage (because of buffered output?)
1801 // So output instead with cerr
1802 std::cerr << runMessage << std::endl;
1803 #endif // ifndef WXPLVIEWER_DEBUG
1804
1805 #ifdef PL_WXWIDGETS_IPC3
1806 size_t nbytes;
1807 try
1808 {
1809 // Update the header from the read (i.e.,
1810 // wxPLViewer) side. Warning, this will block indefinitely
1811 // until the read side sends the required data. So
1812 // theoretically you could wait until the next day to launch
1813 // wxPLViewer using gdb and -dev wxwidgets would happily
1814 // wake up and start communicating with it. N.B. we could
1815 // change this infinite timeout later (by changing all
1816 // sem_wait calls in PLThreeSemaphores to sem_timedwait with a
1817 // generic timeout of say 2 minutes before it throws an
1818 // exception). But regardless of the ultimate resolution of
1819 // that issue, the following will not require any
1820 // wxMilliSleep loops.
1821 m_outputMemoryMap.receiveBytes( true, &m_header, sizeof ( MemoryMapHeader ) );
1822 #ifdef PLPLOT_WX_DEBUG_OUTPUT
1823 std::cerr << "After receiveBytes" << std::endl;
1824 std::cerr << "transmissionType = " << static_cast<unsigned int>( m_header.transmissionType ) << std::endl;
1825 std::cerr << "plbufAmountToTransmit = " << m_header.plbufAmountToTransmit << std::endl;
1826 std::cerr << "viewerOpenFlag = " << m_header.viewerOpenFlag << std::endl;
1827 std::cerr << "locateModeFlag = " << m_header.locateModeFlag << std::endl;
1828 std::cerr << "completeFlag = " << m_header.completeFlag << std::endl;
1829 #endif // #ifdef PLPLOT_WX_DEBUG_OUTPUT
1830 }
1831 catch ( const char *message )
1832 {
1833 plwarn( message );
1834 plwarn( "wxPLDevice::SetupMemoryMap: error" );
1835 }
1836 catch ( ... )
1837 {
1838 plwarn( "wxPLDevice::SetupMemoryMap: Unknown error" );
1839 }
1840 // This value is generated by the read side.
1841 size_t &viewerSignal = m_header.viewerOpenFlag;
1842 #else // #ifdef PL_WXWIDGETS_IPC3
1843
1844 #ifndef WXPLVIEWER_DEBUG
1845 size_t maxTries = 1000;
1846 #else // ifndef WXPLVIEWER_DEBUG
1847 size_t maxTries = 100000;
1848 #endif // ifndef WXPLVIEWER_DEBUG
1849 //wait until the viewer signals it has opened the map file
1850 size_t counter = 0;
1851 size_t &viewerSignal = header->viewerOpenFlag;
1852 while ( counter < maxTries && viewerSignal == 0 )
1853 {
1854 wxMilliSleep( 10 );
1855 ++counter;
1856 }
1857 #endif // #ifdef PL_WXWIDGETS_IPC3
1858 if ( viewerSignal == 0 )
1859 plwarn( NAME_wxPLViewer " failed to signal it has found the shared memory." );
1860 }
1861 PLPLOT_wxLogDebug( "SetupMemoryMap(): leave" );
1862 }
1863
1864 void wxPLDevice::Locate( PLStream * pls, PLGraphicsIn * graphicsIn )
1865 {
1866 if ( !m_dc && m_outputMemoryMap.isValid() )
1867 {
1868 #ifdef PL_WXWIDGETS_IPC3
1869 TransmitBuffer( pls, transmissionLocate );
1870 m_outputMemoryMap.receiveBytes( true, &m_header, sizeof ( MemoryMapHeader ) );
1871 *graphicsIn = m_header.graphicsIn;
1872 #else // #ifdef PL_WXWIDGETS_IPC3
1873 MemoryMapHeader *header = (MemoryMapHeader *) ( m_outputMemoryMap.getBuffer() );
1874 TransmitBuffer( pls, transmissionLocate );
1875 bool gotResponse = false;
1876 while ( !gotResponse )
1877 {
1878 wxMilliSleep( 100 );
1879 PLNamedMutexLocker lock( &m_mutex );
1880 gotResponse = header->locateModeFlag == 0;
1881 }
1882
1883 PLNamedMutexLocker lock( &m_mutex );
1884 *graphicsIn = header->graphicsIn;
1885 #endif //ifdef PL_WXWIDGETS_IPC3
1886 }
1887 else
1888 {
1889 plwarn( "plGetCursor cannot be used when the user supplies a wxDC or until " NAME_wxPLViewer " is initialised" );
1890 graphicsIn->dX = -1;
1891 graphicsIn->dY = -1;
1892 graphicsIn->pX = -1;
1893 graphicsIn->pY = -1;
1894 }
1895 }
1896
1897 //--------------------------------------------------------------------------
1898 // wxRegion wxPLDevice::GetClipRegion()
1899 // Gets the current clip region from plplot as a wxRegion
1900 //--------------------------------------------------------------------------
1901
1902 wxRegion wxPLDevice::GetClipRegion()
1903 {
1904 PLINT rcx[4], rcy[4];
1905 difilt_clip( rcx, rcy );
1906
1907 wxPoint cpoints[4];
1908 for ( int i = 0; i < 4; i++ )
1909 {
1910 cpoints[i].x = rcx[i] / m_xScale;
1911 cpoints[i].y = m_height - rcy[i] / m_yScale;
1912 }
1913 return wxRegion( 4, cpoints );
1914 }
wxPLDevice::m_interactiveTextGcdc
wxGCDC * m_interactiveTextGcdc
Definition: wxwidgets.h:157
plP_script_scale
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
Definition: plsym.c:1302
wxPLDevice::SetColor
void SetColor(PLStream *pls)
Definition: wxwidgets_dev.cpp:1055
wxPLDevice::Flush
void Flush(PLStream *pls)
Definition: wxwidgets_dev.cpp:1417
header
const char header[]
Definition: deltaT-gen.c:41
TextObjectsChanger::TextObjectsChanger
TextObjectsChanger(wxDC *dc, const wxFont &font, const wxColour &textForeground, const wxColour &textBackground)
Definition: wxwidgets_dev.cpp:546
wxPLDevice::m_plplotEdgeLength
const PLFLT m_plplotEdgeLength
Definition: wxwidgets.h:162
wxPLDevice::m_interactiveTextImage
wxImage m_interactiveTextImage
Definition: wxwidgets.h:156
plgesc
void plgesc(char *p_esc)
Definition: plcore.c:3914
fontWeightLookup
const int fontWeightLookup[2]
Definition: wxwidgets.h:257
Rand::m_seed
unsigned int m_seed
Definition: wxwidgets_dev.cpp:693
PLNamedMutex::isValid
bool isValid()
Definition: wxwidgets_comms.cpp:752
MemoryMapHeader::completeFlag
size_t completeFlag
Definition: wxwidgets_comms.h:75
plspage
#define plspage
Definition: plplot.h:831
DrawingObjectsChanger::~DrawingObjectsChanger
~DrawingObjectsChanger()
Definition: wxwidgets_dev.cpp:484
DrawingObjectsChanger::m_brush
wxBrush m_brush
Definition: wxwidgets_dev.cpp:495
wxPLDevice::Locate
void Locate(PLStream *pls, PLGraphicsIn *graphicsIn)
Definition: wxwidgets_dev.cpp:1864
transmissionRegular
const unsigned char transmissionRegular
Definition: wxwidgets_comms.h:40
EscText::just
PLFLT just
Definition: plplotP.h:708
plP_fci2hex
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
transmissionLocate
const unsigned char transmissionLocate
Definition: wxwidgets_comms.h:44
DrawingObjectsChanger
Definition: wxwidgets_dev.cpp:470
PLColor::b
unsigned char b
Definition: plplot.h:550
PLStream::dev_fill1
PLINT dev_fill1
Definition: plstrm.h:571
Font::getFci
PLUNICODE getFci() const
Definition: wxwidgets.h:53
Font
Definition: wxwidgets.h:47
PLGraphicsIn::dX
PLFLT dX
Definition: plplot.h:442
OriginChanger::m_yOriginOld
wxCoord m_yOriginOld
Definition: wxwidgets_dev.cpp:459
PLStream::plbuf_top
size_t plbuf_top
Definition: plstrm.h:650
Rand
Definition: wxwidgets_dev.cpp:641
TextObjectsSaver::m_textBackground
wxColour m_textBackground
Definition: wxwidgets_dev.cpp:532
wxPLDevice::m_yAspect
PLFLT m_yAspect
Definition: wxwidgets.h:168
fontStyleLookup
const int fontStyleLookup[3]
Definition: wxwidgets.h:251
wxPLDevice::wxPLDevice
wxPLDevice(PLStream *pls, char *mfo, PLINT text, PLINT hrshsym)
Definition: wxwidgets_dev.cpp:795
PLUNICODE
PLUINT PLUNICODE
Definition: plplot.h:201
ROUND
#define ROUND(a)
Definition: plplotP.h:202
Rand::Rand
Rand()
Definition: wxwidgets_dev.cpp:644
plP_affine_identity
void plP_affine_identity(PLFLT *affine_vector)
Definition: plaffine.c:56
wxPLDevice::SetWidth
void SetWidth(PLStream *pls)
Definition: wxwidgets_dev.cpp:1042
PlDevice::m_prevFci
PLUNICODE m_prevFci
Definition: wxwidgets.h:110
wxwidgets.h
PLStream::xdpi
PLFLT xdpi
Definition: plstrm.h:616
PLStream::dev_text
PLINT dev_text
Definition: plstrm.h:572
PlDevice::m_prevBaseFontSize
PLFLT m_prevBaseFontSize
Definition: wxwidgets.h:108
TextObjectsChanger::TextObjectsChanger
TextObjectsChanger(wxDC *dc, FontGrabber &fontGrabber, PLUNICODE fci, PLFLT size, bool underlined, const wxColour &textForeground, const wxColour &textBackground)
Definition: wxwidgets_dev.cpp:562
PLPLOT_MM_PER_INCH
#define PLPLOT_MM_PER_INCH
Definition: plplotP.h:313
PLStream::dev_npts
PLINT dev_npts
Definition: plstrm.h:581
PlDevice::PlDevice
PlDevice()
Definition: wxwidgets_dev.cpp:64
wxPLDevice::m_fixedAspect
bool m_fixedAspect
Definition: wxwidgets.h:170
plFontToWxFontParameters
void plFontToWxFontParameters(PLUNICODE fci, PLFLT scaledFontSize, wxFontFamily &family, int &style, int &weight, int &pt)
Definition: wxwidgets_dev.cpp:696
PLStream::color
PLINT color
Definition: plstrm.h:569
PLStream::dev_unicode
PLINT dev_unicode
Definition: plstrm.h:747
Font::getWxFont
wxFont getWxFont()
Definition: wxwidgets_dev.cpp:746
TextObjectsSaver::m_font
wxFont m_font
Definition: wxwidgets_dev.cpp:530
wxPLDevice::~wxPLDevice
virtual ~wxPLDevice(void)
Definition: wxwidgets_dev.cpp:900
Scaler::m_xScaleOld
double m_xScaleOld
Definition: wxwidgets_dev.cpp:427
PLStream::plbuf_write
PLINT plbuf_write
Definition: plstrm.h:567
MAX
#define MAX(a, b)
Definition: dsplint.c:28
PLStream::dev_clear
PLINT dev_clear
Definition: plstrm.h:572
PLStream::diorot
PLFLT diorot
Definition: plstrm.h:661
PLColor::a
PLFLT a
Definition: plplot.h:551
PlDevice::m_prevLevel
PLINT m_prevLevel
Definition: wxwidgets.h:109
PLMemoryMap::getBuffer
char * getBuffer()
Definition: wxwidgets_comms.h:200
wxPLDevice::SetXorMode
void SetXorMode(bool on)
Definition: wxwidgets_dev.cpp:1069
wxPLDevice::m_useDcTextTransform
bool m_useDcTextTransform
Definition: wxwidgets.h:147
MemoryMapHeader::viewerOpenFlag
size_t viewerOpenFlag
Definition: wxwidgets_comms.h:73
TextObjectsChanger::m_saver
TextObjectsSaver m_saver
Definition: wxwidgets_dev.cpp:574
wxPLDevice::m_brush
wxBrush m_brush
Definition: wxwidgets.h:152
wxPLDevice::FillPolygon
void FillPolygon(PLStream *pls)
Definition: wxwidgets_dev.cpp:1003
OriginChanger::~OriginChanger
~OriginChanger()
Definition: wxwidgets_dev.cpp:451
wxPLDevice::DrawLine
void DrawLine(short x1a, short y1a, short x2a, short y2a)
Definition: wxwidgets_dev.cpp:933
wxPLDevice::ClearBackground
void ClearBackground(PLStream *pls, PLINT x1=-1, PLINT y1=-1, PLINT x2=-1, PLINT y2=-1)
Definition: wxwidgets_dev.cpp:970
Font::createFont
void createFont()
Definition: wxwidgets_dev.cpp:728
wxPLDevice::m_lineSpacing
PLFLT m_lineSpacing
Definition: wxwidgets.h:182
NAME_wxPLViewer
#define NAME_wxPLViewer
Definition: plplot_config.h:310
OriginChanger::m_xOriginOld
wxCoord m_xOriginOld
Definition: wxwidgets_dev.cpp:458
PLMemoryMap::getSize
size_t getSize()
Definition: wxwidgets_comms.h:201
PLPLOT_MAX_PATH
#define PLPLOT_MAX_PATH
Definition: plplotP.h:446
TextObjectsChanger::TextObjectsChanger
TextObjectsChanger(wxDC *dc, const wxFont &font)
Definition: wxwidgets_dev.cpp:556
BUILD_DIR
#define BUILD_DIR
Definition: plplot_config.h:24
PlDevice::DrawTextSection
virtual void DrawTextSection(wxString section, wxCoord xOrigin, wxCoord yOrigin, wxCoord x, wxCoord y, PLFLT *transform, PLFLT scaledFontSize, bool drawText, bool underlined, PLUNICODE fci, unsigned char red, unsigned char green, unsigned char blue, PLFLT alpha, PLFLT &yScale, wxCoord &sectionWidth, wxCoord &sectionHeight, wxCoord &sectionDepth)
Definition: wxwidgets.h:105
TextObjectsSaver::m_dc
wxDC * m_dc
Definition: wxwidgets_dev.cpp:529
OriginChanger::m_dc
wxDC * m_dc
Definition: wxwidgets_dev.cpp:457
transmissionClose
const unsigned char transmissionClose
Definition: wxwidgets_comms.h:49
PLStream::dev_x
short * dev_x
Definition: plstrm.h:582
Clipper::isEverythingClipped
bool isEverythingClipped()
Definition: wxwidgets_dev.cpp:621
wxPLDevice::DrawPolyline
void DrawPolyline(short *xa, short *ya, PLINT npts)
Definition: wxwidgets_dev.cpp:951
PLINT
int PLINT
Definition: plplot.h:181
TextObjectsSaver
Definition: wxwidgets_dev.cpp:506
wxPLDevice::PreDestructorTidy
void PreDestructorTidy(PLStream *pls)
Definition: wxwidgets_dev.cpp:922
MIN
#define MIN(a, b)
Definition: dsplint.c:29
Scaler::Scaler
Scaler(wxDC *dc, double xScale, double yScale)
Definition: wxwidgets_dev.cpp:411
wxPLDevice::m_pen
wxPen m_pen
Definition: wxwidgets.h:151
Clipper::m_dc
wxDC * m_dc
Definition: wxwidgets_dev.cpp:626
wxPLDevice::m_height
PLFLT m_height
Definition: wxwidgets.h:164
wxPLDevice::SetupMemoryMap
void SetupMemoryMap()
Definition: wxwidgets_dev.cpp:1683
plMemoryMapReservedSpace
const PLINT plMemoryMapReservedSpace
Definition: wxwidgets_comms.h:180
PLColor::g
unsigned char g
Definition: plplot.h:549
PLNamedMutex::create
void create(const char *name, bool aquireOnCreate=false)
Definition: wxwidgets_comms.cpp:670
wxPLDevice::m_localBufferPosition
size_t m_localBufferPosition
Definition: wxwidgets.h:197
wxPLDevice::m_width
PLFLT m_width
Definition: wxwidgets.h:163
EscText
Definition: plplotP.h:699
wxPLDevice::m_xScale
PLFLT m_xScale
Definition: wxwidgets.h:165
PLStream::termin
PLINT termin
Definition: plstrm.h:568
Rand::Rand
Rand(unsigned int seed)
Definition: wxwidgets_dev.cpp:664
Font::getUnderlined
bool getUnderlined() const
Definition: wxwidgets.h:55
TRUE
#define TRUE
Definition: plplotP.h:176
PLStream::dev_hrshsym
PLINT dev_hrshsym
Definition: plstrm.h:753
PLStream::ylength
PLINT ylength
Definition: plstrm.h:617
TextObjectsChanger
Definition: wxwidgets_dev.cpp:543
FontGrabber::GetFont
Font GetFont(PLUNICODE fci, PLFLT scaledFontSize, bool underlined)
Definition: wxwidgets_dev.cpp:775
PlDevice::DrawTextLine
void DrawTextLine(PLUNICODE *ucs4, int ucs4Len, wxCoord xOrigin, wxCoord yOrigin, wxCoord x, wxCoord y, PLFLT *transform, PLFLT baseFontSize, bool drawText, bool &underlined, PLUNICODE &fci, unsigned char red, unsigned char green, unsigned char blue, PLFLT alpha, wxCoord &textWidth, wxCoord &textHeight, wxCoord &textDepth)
Definition: wxwidgets_dev.cpp:242
FALSE
#define FALSE
Definition: plplotP.h:177
PlDevice::drawText
void drawText(PLStream *pls, EscText *args)
Definition: wxwidgets_dev.cpp:81
difilt_clip
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition: plcore.c:1603
wxPLDevice::m_dc
wxDC * m_dc
Definition: wxwidgets.h:146
PL_FCI_STYLE
#define PL_FCI_STYLE
Definition: plplot.h:377
PLMemoryMap::isValid
bool isValid()
Definition: wxwidgets_comms.h:190
MemoryMapHeader::readLocation
size_t readLocation
Definition: wxwidgets_comms.h:80
PLPLOT_DEFAULT_WIDTH_PIXELS
#define PLPLOT_DEFAULT_WIDTH_PIXELS
Definition: plplotP.h:329
Clipper::m_boxOld
wxRect m_boxOld
Definition: wxwidgets_dev.cpp:627
fontFamilyLookup
const wxFontFamily fontFamilyLookup[5]
Definition: wxwidgets.h:243
plInBuildTree
int plInBuildTree()
Definition: plcore.c:2888
PLStream::verbose
PLINT verbose
Definition: plstrm.h:527
PLStream::get_string_length
PLINT get_string_length
Definition: plstrm.h:787
Clipper
Definition: wxwidgets_dev.cpp:591
PLNamedMutexLocker
Definition: wxwidgets_comms.h:245
PLPLOT_DEFAULT_PIXELS_PER_INCH
#define PLPLOT_DEFAULT_PIXELS_PER_INCH
Definition: plplotP.h:326
plP_setpxl
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
wxPLDevice::m_mfo
char m_mfo[PLPLOT_MAX_PATH]
Definition: wxwidgets.h:190
wxPLDevice::GetClipRegion
wxRegion GetClipRegion()
Definition: wxwidgets_dev.cpp:1902
transmissionComplete
const unsigned char transmissionComplete
Definition: wxwidgets_comms.h:46
wxPLDevice::TransmitBuffer
void TransmitBuffer(PLStream *pls, unsigned char transmissionType)
Definition: wxwidgets_dev.cpp:1430
Scaler
Definition: wxwidgets_dev.cpp:408
plDevs.h
plP_affine_multiply
void plP_affine_multiply(PLFLT *affine_vectorA, PLFLT_VECTOR affine_vectorB, PLFLT_VECTOR affine_vectorC)
Definition: plaffine.c:184
PLStream::ydpi
PLFLT ydpi
Definition: plstrm.h:616
wxPLDevice::m_xAspect
PLFLT m_xAspect
Definition: wxwidgets.h:167
BIN_DIR
#define BIN_DIR
Definition: plplot_config.h:21
pls
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
plP_setphy
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
transmissionBeginPage
const unsigned char transmissionBeginPage
Definition: wxwidgets_comms.h:43
plgfci
#define plgfci
Definition: plplot.h:735
Font::getSize
PLFLT getSize() const
Definition: wxwidgets.h:54
PLStream::xlength
PLINT xlength
Definition: plstrm.h:617
PLStream::xpmm
PLFLT xpmm
Definition: plstrm.h:707
wxPLDevice::m_yScale
PLFLT m_yScale
Definition: wxwidgets.h:166
transmissionPartial
const unsigned char transmissionPartial
Definition: wxwidgets_comms.h:45
wxPLDevice::m_scale
PLFLT m_scale
Definition: wxwidgets.h:169
operator==
bool operator==(const Font &lhs, const Font &rhs)
Definition: wxwidgets_dev.cpp:753
MemoryMapHeader
Definition: wxwidgets_comms.h:71
EscText::unicode_array_len
unsigned short unicode_array_len
Definition: plplotP.h:736
PLStream::dev_y
short * dev_y
Definition: plstrm.h:582
PLStream
Definition: plstrm.h:523
DrawingObjectsChanger::DrawingObjectsChanger
DrawingObjectsChanger(wxDC *dc, const wxPen &pen, const wxBrush &brush)
Definition: wxwidgets_dev.cpp:473
Scaler::m_dc
wxDC * m_dc
Definition: wxwidgets_dev.cpp:426
Scaler::~Scaler
~Scaler()
Definition: wxwidgets_dev.cpp:420
PLPLOT_POINTS_PER_INCH
#define PLPLOT_POINTS_PER_INCH
Definition: plplotP.h:314
wxPLDevice::FixAspectRatio
void FixAspectRatio(bool fix)
Definition: wxwidgets_dev.cpp:1412
text
static int text
Definition: ps.c:77
max
int max(int a, int b)
Definition: plplot_octaveOCTAVE_wrap.cxx:2492
MemoryMapHeader::graphicsIn
PLGraphicsIn graphicsIn
Definition: wxwidgets_comms.h:83
wxPLDevice::m_mutex
PLNamedMutex m_mutex
Definition: wxwidgets.h:195
wxPLDevice::EndPage
void EndPage(PLStream *pls)
Definition: wxwidgets_dev.cpp:1315
PLStream::dev_data
void * dev_data
Definition: plstrm.h:596
PLGraphicsIn::pX
int pX
Definition: plplot.h:441
PLFLT
float PLFLT
Definition: plplot.h:163
PLStream::graphx
PLINT graphx
Definition: plstrm.h:568
Rand::operator()
unsigned int operator()()
Definition: wxwidgets_dev.cpp:668
Font::Font
Font()
Definition: wxwidgets_dev.cpp:710
transmissionSkipFileEnd
const unsigned char transmissionSkipFileEnd
Definition: wxwidgets_comms.h:41
PL_FCI_FAMILY
#define PL_FCI_FAMILY
Definition: plplot.h:376
command
static Tcl_DString command
Definition: tkMain.c:121
PLStream::chrht
PLFLT chrht
Definition: plstrm.h:686
plgcolbga
#define plgcolbga
Definition: plplot.h:727
pt
Definition: plgridd.c:85
transmissionRequestTextSize
const unsigned char transmissionRequestTextSize
Definition: wxwidgets_comms.h:47
TextObjectsSaver::TextObjectsSaver
TextObjectsSaver(wxDC *dc)
Definition: wxwidgets_dev.cpp:509
Clipper::Clipper
Clipper(wxDC *dc, const wxRect &rect)
Definition: wxwidgets_dev.cpp:594
PL_FCI_WEIGHT
#define PL_FCI_WEIGHT
Definition: plplot.h:378
Clipper::~Clipper
~Clipper()
Definition: wxwidgets_dev.cpp:610
TextObjectsSaver::m_textForeground
wxColour m_textForeground
Definition: wxwidgets_dev.cpp:531
PLMemoryMap::create
void create(const char *name, PLINT size, bool mustExist, bool mustNotExist)
Definition: wxwidgets_comms.cpp:367
DrawingObjectsChanger::m_dc
wxDC * m_dc
Definition: wxwidgets_dev.cpp:493
PLColor::r
unsigned char r
Definition: plplot.h:548
PLPLOT_wxLogDebug
#define PLPLOT_wxLogDebug(string)
Definition: wxPLplot_nanosec.h:24
PLStream::nopause
PLINT nopause
Definition: plstrm.h:568
PLStream::plbuf_buffer
void * plbuf_buffer
Definition: plstrm.h:649
PLStream::width
PLFLT width
Definition: plstrm.h:552
plwarn
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
MemoryMapHeader::writeLocation
size_t writeLocation
Definition: wxwidgets_comms.h:81
wxPLDevice::SetSize
void SetSize(PLStream *pls, int width, int height)
Definition: wxwidgets_dev.cpp:1351
EscText::y
PLINT y
Definition: plplotP.h:713
Clipper::m_clipEverything
bool m_clipEverything
Definition: wxwidgets_dev.cpp:628
wxPLDevice::SetDC
void SetDC(PLStream *pls, wxDC *dc)
Definition: wxwidgets_dev.cpp:1081
plreplot
#define plreplot
Definition: plplot.h:788
PLStream::dev_dash
PLINT dev_dash
Definition: plstrm.h:571
wxPLDevice::DrawTextSection
void DrawTextSection(wxString section, wxCoord xOrigin, wxCoord yOrigin, wxCoord x, wxCoord y, PLFLT *transform, PLFLT scaledFontSize, bool drawText, bool underlined, PLUNICODE fci, unsigned char red, unsigned char green, unsigned char blue, PLFLT alpha, PLFLT &yScale, wxCoord &sectionWidth, wxCoord &sectionHeight, wxCoord &sectionDepth)
Definition: wxwidgets_dev.cpp:1140
PLStream::curcolor
PLColor curcolor
Definition: plstrm.h:543
PlDevice::m_prevSymbolHeight
wxCoord m_prevSymbolHeight
Definition: wxwidgets.h:112
wxPLDevice::BeginPage
void BeginPage(PLStream *pls)
Definition: wxwidgets_dev.cpp:1331
PLGraphicsIn::dY
PLFLT dY
Definition: plplot.h:442
hrshsym
static int hrshsym
Definition: ps.c:79
transmissionEndOfPageNoPause
const unsigned char transmissionEndOfPageNoPause
Definition: wxwidgets_comms.h:48
MemoryMapHeader::locateModeFlag
size_t locateModeFlag
Definition: wxwidgets_comms.h:74
FontGrabber::FontGrabber
FontGrabber()
Definition: wxwidgets_dev.cpp:765
Scaler::m_yScaleOld
double m_yScaleOld
Definition: wxwidgets_dev.cpp:428
transmissionEndOfPage
const unsigned char transmissionEndOfPage
Definition: wxwidgets_comms.h:42
PLStream::debug
PLINT debug
Definition: plstrm.h:527
EscText::x
PLINT x
Definition: plplotP.h:712
wxPLDevice::m_outputMemoryMap
PLMemoryMap m_outputMemoryMap
Definition: wxwidgets.h:198
PLStream::string_length
PLFLT string_length
Definition: plstrm.h:786
TextObjectsSaver::~TextObjectsSaver
~TextObjectsSaver()
Definition: wxwidgets_dev.cpp:519
PLStream::dev_flush
PLINT dev_flush
Definition: plstrm.h:571
PLPLOT_DEFAULT_HEIGHT_PIXELS
#define PLPLOT_DEFAULT_HEIGHT_PIXELS
Definition: plplotP.h:330
plP_gphy
void plP_gphy(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition: plcore.c:4198
PlDevice::m_prevSymbol
PLUNICODE m_prevSymbol
Definition: wxwidgets.h:107
PLGraphicsIn::pY
int pY
Definition: plplot.h:441
PlDevice::m_prevSymbolWidth
wxCoord m_prevSymbolWidth
Definition: wxwidgets.h:111
DrawingObjectsChanger::m_pen
wxPen m_pen
Definition: wxwidgets_dev.cpp:494
FontGrabber
Definition: wxwidgets.h:70
EscText::unicode_array
PLUNICODE * unicode_array
Definition: plplotP.h:735
PLStream::dev
void * dev
Definition: plstrm.h:594
OriginChanger::OriginChanger
OriginChanger(wxDC *dc, wxCoord xOrigin, wxCoord yOrigin)
Definition: wxwidgets_dev.cpp:442
M_PI
#define M_PI
Definition: plplotP.h:119
OriginChanger
Definition: wxwidgets_dev.cpp:439
PLStream::dev_fill0
PLINT dev_fill0
Definition: plstrm.h:571
wxPLDevice::m_fontGrabber
FontGrabber m_fontGrabber
Definition: wxwidgets.h:175
EscText::xform
PLFLT * xform
Definition: plplotP.h:709
PLStream::dev_eofill
PLINT dev_eofill
Definition: plstrm.h:788
PlDevice::m_prevSymbolDepth
wxCoord m_prevSymbolDepth
Definition: wxwidgets.h:113
PLMemoryMap::close
void close()
Definition: wxwidgets_comms.cpp:618
GRAPHICS_MODE
#define GRAPHICS_MODE
Definition: plplotP.h:288
PL_FCI_MARK
#define PL_FCI_MARK
Definition: plplot.h:370
wxPLDevice::m_gc
wxGraphicsContext * m_gc
Definition: wxwidgets.h:150
PLStream::has_string_length
PLINT has_string_length
Definition: plstrm.h:785
PLGraphicsIn
Definition: plplot.h:433