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