PLplot  5.9.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
wingcc.c
Go to the documentation of this file.
1 // $Id: wingcc.c 12404 2013-07-07 12:59:52Z arjenmarkus $
2 //
3 // PLplot WIN32 under GCC device driver.
4 //
5 // Copyright (C) 2004 Andrew Roach
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 #include "plDevs.h"
25 
26 #ifdef PLD_wingcc
27 
28 #include <string.h>
29 #include <windows.h>
30 #if !defined ( __CYGWIN__ )
31 #include <tchar.h>
32 #else
33 #include <winnt.h>
34 #define _T( a ) __TEXT( a )
35 #endif
36 #ifdef _WIN64
37 #define GWL_USERDATA GWLP_USERDATA
38 #define GCL_HCURSOR GCLP_HCURSOR
39 #endif
40 
41 #include "plplotP.h"
42 #include "drivers.h"
43 #include "plevent.h"
44 
45 #ifdef PL_HAVE_FREETYPE
46 
47 //
48 // Freetype support has been added to the wingcc driver using the
49 // plfreetype.c module, and implemented as a driver-specific optional extra
50 // invoked via the -drvopt command line toggle. It uses the
51 // "PLESC_HAS_TEXT" command for rendering within the driver.
52 //
53 // Freetype support is turned on/off at compile time by defining
54 // "PL_HAVE_FREETYPE".
55 //
56 // To give the user some level of control over the fonts that are used,
57 // environmental variables can be set to over-ride the definitions used by
58 // the five default plplot fonts.
59 //
60 // Freetype rendering is used with the command line "-drvopt text".
61 // Anti-aliased fonts can be used by issuing "-drvopt text,smooth"
62 //
63 
64 #include "plfreetype.h"
65 
66 #ifndef max_number_of_grey_levels_used_in_text_smoothing
67 #define max_number_of_grey_levels_used_in_text_smoothing 64
68 #endif
69 
70 #endif
71 
72 
73 // Device info
74 
75 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wingcc = "wingcc:Win32 (GCC):1:wingcc:9:wingcc\n";
76 
77 // Struct to hold device-specific info.
78 
79 typedef struct
80 {
81  PLFLT scale; // scaling factor to "blow up" to the "virtual" page in removing hidden lines
82  PLINT width; // Window width (which can change)
83  PLINT height; // Window Height
84 
85  PLFLT PRNT_scale;
86  PLINT PRNT_width;
87  PLINT PRNT_height;
88 
89  char FT_smooth_text;
90 //
91 // WIN32 API variables
92 //
93 
94  COLORREF colour; // Current Colour
95  COLORREF oldcolour; // Used for high-speed background erasing
96  MSG msg; // A Win32 message structure.
97  WNDCLASSEX wndclass; // An extended window class structure.
98  HWND hwnd; // Handle for the main window.
99  HPEN pen; // Windows pen used for drawing
100  HDC hdc; // Driver Context
101  HDC hdc2; // Driver Context II - used for Blitting
102  HDC SCRN_hdc; // The screen's context
103  HDC PRNT_hdc; // used for printing
104  PAINTSTRUCT ps; // used to paint the client area of a window owned by that application
105  RECT rect; // defines the coordinates of the upper-left and lower-right corners of a rectangle
106  RECT oldrect; // used for re-sizing comparisons
107  RECT paintrect; // used for painting etc...
108  HBRUSH fillbrush; // brush used for fills
109  HCURSOR cursor; // Current windows cursor for this window
110  HBITMAP bitmap; // Bitmap of current display; used for fast redraws via blitting
111  HGDIOBJ oldobject; // Used for tracking objects probably not really needed but
112  HMENU PopupMenu;
113 
114  PLINT draw_mode;
115  char truecolour; // Flag to indicate 24 bit mode
116  char waiting; // Flag to indicate drawing is done, and it is waiting;
117  // we only do a windows redraw if plplot is plotting
118  char enterresize; // Used to keep track of reszing messages from windows
119  char already_erased; // Used to track first and only first backgroudn erases
120 
121  struct wingcc_Dev *push; // A copy of the entire structure used when printing
122  // We push and pop it off a virtual stack
123 } wingcc_Dev;
124 
125 
127 
128 void plD_init_wingcc( PLStream * );
129 void plD_line_wingcc( PLStream *, short, short, short, short );
130 void plD_polyline_wingcc( PLStream *, short *, short *, PLINT );
131 void plD_eop_wingcc( PLStream * );
132 void plD_bop_wingcc( PLStream * );
133 void plD_tidy_wingcc( PLStream * );
134 void plD_state_wingcc( PLStream *, PLINT );
135 void plD_esc_wingcc( PLStream *, PLINT, void * );
136 
137 #ifdef PL_HAVE_FREETYPE
138 
139 static void plD_pixel_wingcc( PLStream *pls, short x, short y );
140 static void plD_pixelV_wingcc( PLStream *pls, short x, short y );
141 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y );
142 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour );
143 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour );
144 static void init_freetype_lv1( PLStream *pls );
145 static void init_freetype_lv2( PLStream *pls );
146 
147 #endif
148 
149 
150 //--------------------------------------------------------------------------
151 // Local Function definitions and function-like defines
152 //--------------------------------------------------------------------------
153 
154 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size );
155 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size );
156 static void Resize( PLStream *pls );
157 static void plD_fill_polygon_wingcc( PLStream *pls );
158 static void CopySCRtoBMP( PLStream *pls );
159 static void PrintPage( PLStream *pls );
160 static void UpdatePageMetrics( PLStream *pls, char flag );
161 
162 #define SetRegStringValue( a, b, c ) SetRegValue( a, b, c, REG_SZ, strlen( c ) + 1 )
163 #define SetRegBinaryValue( a, b, c, d ) SetRegValue( a, b, (char *) c, REG_BINARY, d )
164 #define SetRegIntValue( a, b, c ) SetRegValue( a, b, (char *) c, REG_DWORD, 4 )
165 #define GetRegStringValue( a, b, c, d ) GetRegValue( a, b, c, d )
166 #define GetRegIntValue( a, b, c ) GetRegValue( a, b, (char *) c, 4 )
167 #define GetRegBinaryValue( a, b, c, d ) GetRegValue( a, b, (char *) c, d )
168 
169 //--------------------------------------------------------------------------
170 // Some debugging macros
171 //--------------------------------------------------------------------------
172 
173 #if defined ( _MSC_VER )
174  #define Debug( a ) do { if ( pls->debug ) { fprintf( stderr, ( a ) ); } } while ( 0 )
175  #define Debug2( a, b ) do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ) ); } } while ( 0 )
176  #define Debug3( a, b, c ) do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ), ( c ) ); } } while ( 0 )
177 #elif defined ( __BORLANDC__ )
178  #define Debug if ( pls->debug ) printf
179  #define Debug2 if ( pls->debug ) printf
180  #define Debug3 if ( pls->debug ) printf
181 #else
182  #define Verbose( ... ) do { if ( pls->verbose ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
183  #define Debug( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
184  #define Debug2( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
185  #define Debug3( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
186 #endif
187 
188 #define ReportWinError() do { \
189  LPVOID lpMsgBuf; \
190  FormatMessage( \
191  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \
192  NULL, GetLastError(), \
193  MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL ); \
194  MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK | MB_ICONINFORMATION ); \
195  LocalFree( lpMsgBuf ); } while ( 0 )
196 
197 #define CrossHairCursor() do { \
198  dev->cursor = LoadCursor( NULL, IDC_CROSS ); \
199  SetClassLong( dev->hwnd, GCL_HCURSOR, (long) dev->cursor ); \
200  SetCursor( dev->cursor ); } while ( 0 )
201 
202 #define NormalCursor() do { \
203  dev->cursor = LoadCursor( NULL, IDC_ARROW ); \
204  SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \
205  SetCursor( dev->cursor ); } while ( 0 )
206 
207 #define BusyCursor() do { \
208  dev->cursor = LoadCursor( NULL, IDC_WAIT ); \
209  SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \
210  SetCursor( dev->cursor ); } while ( 0 )
211 
212 #define PopupPrint 0x08A1
213 #define PopupNextPage 0x08A2
214 #define PopupQuit 0x08A3
215 
216 
218 {
219 #ifndef ENABLE_DYNDRIVERS
220  pdt->pl_MenuStr = "Win32 GCC device";
221  pdt->pl_DevName = "wingcc";
222 #endif
224  pdt->pl_seq = 9;
225  pdt->pl_init = (plD_init_fp) plD_init_wingcc;
226  pdt->pl_line = (plD_line_fp) plD_line_wingcc;
227  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wingcc;
228  pdt->pl_eop = (plD_eop_fp) plD_eop_wingcc;
229  pdt->pl_bop = (plD_bop_fp) plD_bop_wingcc;
230  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wingcc;
231  pdt->pl_state = (plD_state_fp) plD_state_wingcc;
232  pdt->pl_esc = (plD_esc_fp) plD_esc_wingcc;
233 }
234 
235 static TCHAR* szWndClass = _T( "PlplotWin" );
236 
237 
238 //--------------------------------------------------------------------------
239 // This is the window function for the plot window. Whenever a message is
240 // dispatched using DispatchMessage (or sent with SendMessage) this function
241 // gets called with the contents of the message.
242 //--------------------------------------------------------------------------
243 
244 LRESULT CALLBACK PlplotWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
245 {
246  PLStream *pls = NULL;
247  wingcc_Dev *dev = NULL;
248 
249 //
250 // The window carries a 32bit user defined pointer which points to the
251 // plplot stream (pls). This is used for tracking the window.
252 // Unfortunately, this is "attached" to the window AFTER it is created
253 // so we can not initialise PLStream or wingcc_Dev "blindly" because
254 // they may not yet have been initialised.
255 // WM_CREATE is called before we get to initialise those variables, so
256 // we wont try to set them.
257 //
258 
259  if ( nMsg == WM_CREATE )
260  {
261  return ( 0 );
262  }
263  else
264  {
265 #ifndef _WIN64
266 #undef GetWindowLongPtr
267 #define GetWindowLongPtr GetWindowLong
268 #endif
269  pls = (PLStream *) GetWindowLongPtr( hwnd, GWL_USERDATA ); // Try to get the address to pls for this window
270  if ( pls ) // If we got it, then we will initialise this windows plplot private data area
271  {
272  dev = (wingcc_Dev *) pls->dev;
273  }
274  }
275 
276 //
277 // Process the windows messages
278 //
279 // Everything except WM_CREATE is done here and it is generally hoped that
280 // pls and dev are defined already by this stage.
281 // That will be true MOST of the time. Some times WM_PAINT will be called
282 // before we get to initialise the user data area of the window with the
283 // pointer to the windows plplot stream
284 //
285 
286  switch ( nMsg )
287  {
288  case WM_DESTROY:
289  if ( dev )
290  Debug( "WM_DESTROY\t" );
291  PostQuitMessage( 0 );
292  return ( 0 );
293  break;
294 
295  case WM_PAINT:
296  if ( dev )
297  {
298  Debug( "WM_PAINT\t" );
299  if ( GetUpdateRect( dev->hwnd, &dev->paintrect, TRUE ) )
300  {
301  BusyCursor();
302  BeginPaint( dev->hwnd, &dev->ps );
303 
304  if ( ( dev->waiting == 1 ) && ( dev->already_erased == 1 ) )
305  {
306  Debug( "Remaking\t" );
307 
308  if ( dev->ps.fErase )
309  {
310  dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
311  ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 );
312  SetBkColor( dev->hdc, dev->oldcolour );
313  }
314 
315  plRemakePlot( pls );
316  CopySCRtoBMP( pls );
317  dev->already_erased++;
318  }
319  else if ( ( dev->waiting == 1 ) && ( dev->already_erased == 2 ) )
320  {
321  dev->oldobject = SelectObject( dev->hdc2, dev->bitmap );
322  BitBlt( dev->hdc, dev->paintrect.left, dev->paintrect.top,
323  dev->paintrect.right, dev->paintrect.bottom,
324  dev->hdc2, dev->paintrect.left, dev->paintrect.top, SRCCOPY );
325  SelectObject( dev->hdc2, dev->oldobject );
326  }
327 
328  EndPaint( dev->hwnd, &dev->ps );
329  NormalCursor();
330  return ( 0 );
331  }
332  }
333  return ( 1 );
334  break;
335 
336  case WM_SIZE:
337  if ( dev )
338  {
339  Debug( "WM_SIZE\t" );
340 
341  if ( dev->enterresize == 0 )
342  Resize( pls );
343  }
344  return ( 0 );
345  break;
346 
347  case WM_ENTERSIZEMOVE:
348  if ( dev )
349  {
350  Debug( "WM_ENTERSIZEMOVE\t" );
351  dev->enterresize = 1;
352  }
353  return ( 0 );
354  break;
355 
356 
357  case WM_EXITSIZEMOVE:
358  if ( dev )
359  {
360  Debug( "WM_EXITSIZEMOVE\t" );
361  Resize( pls );
362  dev->enterresize = 0; // Reset the variables that track sizing ops
363  }
364  return ( 0 );
365  break;
366 
367  case WM_ERASEBKGND:
368 
369  if ( dev )
370  {
371  if ( dev->already_erased == 0 )
372  {
373  Debug( "WM_ERASEBKGND\t" );
374 
375  //
376  // This is a new "High Speed" way of filling in the background.
377  // supposidely this executes faster than creating a brush and
378  // filling a rectangle - go figure ?
379  //
380 
381  dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
382  ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 );
383  SetBkColor( dev->hdc, dev->oldcolour );
384 
385  dev->already_erased = 1;
386  return ( 1 );
387  }
388  }
389  return ( 0 );
390  break;
391 
392  case WM_COMMAND:
393  if ( dev )
394  Debug( "WM_COMMAND\t" );
395  return ( 0 );
396  break;
397  }
398 
399  // If we don't handle a message completely we hand it to the system
400  // provided default window function.
401  return DefWindowProc( hwnd, nMsg, wParam, lParam );
402 }
403 
404 
405 //--------------------------------------------------------------------------
406 // plD_init_wingcc()
407 //
408 // Initialize device (terminal).
409 //--------------------------------------------------------------------------
410 
411 void
412 plD_init_wingcc( PLStream *pls )
413 {
414  wingcc_Dev *dev;
415 
416 #ifdef PL_HAVE_FREETYPE
417  static int freetype = 0;
418  static int smooth_text = 0;
419  static int save_reg = 0;
420  FT_Data *FT;
421 
422 //
423 // Variables used for reading the registary keys
424 // might eventually add a user defined pallette here, but for now it just does freetype
425 //
426  TCHAR key_name[] = _T( "Software\\PLplot\\wingcc" );
427  TCHAR Keyword_text[] = _T( "freetype" );
428  TCHAR Keyword_smooth[] = _T( "smooth" );
429 #endif
430 
431  DrvOpt wingcc_options[] = {
432 #ifdef PL_HAVE_FREETYPE
433  { "text", DRV_INT, &freetype, "Use driver text (FreeType)" },
434  { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" },
435  { "save", DRV_INT, &save_reg, "Save defaults to registary" },
436 
437 #endif
438  { NULL, DRV_INT, NULL, NULL }
439  };
440 
441 //
442 // Variable for storing the program name
443 //
444  TCHAR *program;
445  int programlength;
446 
447 // Allocate and initialize device-specific data
448 
449  if ( pls->dev != NULL )
450  free( (void *) pls->dev );
451 
452  pls->dev = calloc( 1, (size_t) sizeof ( wingcc_Dev ) );
453  if ( pls->dev == NULL )
454  plexit( "plD_init_wingcc_Dev: Out of memory." );
455 
456  dev = (wingcc_Dev *) pls->dev;
457 
458  pls->icol0 = 1; // Set a fall back pen colour in case user doesn't
459 
460  pls->termin = 1; // interactive device
461  pls->graphx = GRAPHICS_MODE; // No text mode for this driver (at least for now, might add a console window if I ever figure it out and have the inclination)
462  pls->dev_fill0 = 1; // driver can do solid area fills
463  pls->dev_xor = 1; // driver supports xor mode
464  pls->dev_clear = 0; // driver does not support clear - what is the proper API?
465  pls->dev_dash = 0; // driver can not do dashed lines (yet)
466  pls->plbuf_write = 1; // driver uses the buffer for redraws
467 
468  if ( !pls->colorset )
469  pls->color = 1;
470 
471 
472 #ifdef PL_HAVE_FREETYPE
473 
474 //
475 // Read registry to see if the user has set up default values
476 // for text and smoothing. These will be overriden by anything that
477 // might be given on the command line, so we will load the
478 // values right into the same memory slots we pass to plParseDrvOpts
479 //
480 
481  GetRegIntValue( key_name, Keyword_text, &freetype );
482  GetRegIntValue( key_name, Keyword_smooth, &smooth_text );
483 
484 #endif
485 
486 // Check for and set up driver options
487 
488  plParseDrvOpts( wingcc_options );
489 
490 #ifdef PL_HAVE_FREETYPE
491 
492 //
493 // We will now save the settings to the registary if the user wants
494 //
495 
496  if ( save_reg == 1 )
497  {
498  SetRegIntValue( key_name, Keyword_text, &freetype );
499  SetRegIntValue( key_name, Keyword_smooth, &smooth_text );
500  }
501 
502 #endif
503 
504 // Set up device parameters
505 
506  if ( pls->xlength <= 0 || pls->ylength <= 0 )
507  {
508  // use default width, height of 800x600 if not specifed by -geometry option
509  // or plspage
510  plspage( 0., 0., 800, 600, 0, 0 );
511  }
512 
513  dev->width = pls->xlength - 1; // should I use -1 or not???
514  dev->height = pls->ylength - 1;
515 
516 //
517 // Begin initialising the window
518 //
519 
520  // Initialize the entire structure to zero.
521  memset( &dev->wndclass, 0, sizeof ( WNDCLASSEX ) );
522 
523  // This class is called WinTestWin
524  dev->wndclass.lpszClassName = szWndClass;
525 
526  // cbSize gives the size of the structure for extensibility.
527  dev->wndclass.cbSize = sizeof ( WNDCLASSEX );
528 
529  // All windows of this class redraw when resized.
530  dev->wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC | CS_PARENTDC;
531 
532  // All windows of this class use the WndProc window function.
533  dev->wndclass.lpfnWndProc = PlplotWndProc;
534 
535  // This class is used with the current program instance.
536 
537  dev->wndclass.hInstance = GetModuleHandle( NULL );
538 
539  // Use standard application icon and arrow cursor provided by the OS
540  dev->wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
541  dev->wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
542  dev->wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
543  // Color the background white
544  dev->wndclass.hbrBackground = NULL;
545 
546  dev->wndclass.cbWndExtra = sizeof ( pls );
547 
548 
549  //
550  // Now register the window class for use.
551  //
552 
553  RegisterClassEx( &dev->wndclass );
554 
555  //
556  //convert the program name to wide char if needed
557  //
558 
559 #ifdef UNICODE
560  printf( pls->program );
561  programlength = strlen( pls->program ) + 1;
562  program = malloc( programlength * sizeof ( TCHAR ) );
563  MultiByteToWideChar( CP_UTF8, 0, pls->program, programlength, program, programlength );
564 #else
565  program = pls->program;
566 #endif
567  //
568  // Create our main window using that window class.
569  //
570  dev->hwnd = CreateWindowEx( WS_EX_WINDOWEDGE + WS_EX_LEFT,
571  szWndClass, // Class name
572  program, // Caption
573  WS_OVERLAPPEDWINDOW, // Style
574  pls->xoffset, // Initial x (use default)
575  pls->yoffset, // Initial y (use default)
576  pls->xlength, // Initial x size (use default)
577  pls->ylength, // Initial y size (use default)
578  NULL, // No parent window
579  NULL, // No menu
580  dev->wndclass.hInstance, // This program instance
581  NULL // Creation parameters
582  );
583 
584 #ifdef UNICODE
585  free( program );
586 #endif
587 
588 //
589 // Attach a pointer to the stream to the window's user area
590 // this pointer will be used by the windows call back for
591 // process this window
592 //
593 
594 #ifdef _WIN64
595  SetWindowLongPtr( dev->hwnd, GWL_USERDATA, (LONG_PTR) pls );
596 #else
597  SetWindowLong( dev->hwnd, GWL_USERDATA, (LONG) pls );
598 #endif
599 
600  dev->SCRN_hdc = dev->hdc = GetDC( dev->hwnd );
601 
602 //
603 // Setup the popup menu
604 //
605 
606  dev->PopupMenu = CreatePopupMenu();
607  AppendMenu( dev->PopupMenu, MF_STRING, PopupPrint, _T( "Print" ) );
608  AppendMenu( dev->PopupMenu, MF_STRING, PopupNextPage, _T( "Next Page" ) );
609  AppendMenu( dev->PopupMenu, MF_STRING, PopupQuit, _T( "Quit" ) );
610 
611 #ifdef PL_HAVE_FREETYPE
612 
613  if ( freetype )
614  {
615  pls->dev_text = 1; // want to draw text
616  pls->dev_unicode = 1; // want unicode
617  init_freetype_lv1( pls );
618  FT = (FT_Data *) pls->FT;
619  FT->want_smooth_text = smooth_text;
620  }
621 
622 #endif
623 
624 
625 
626  plD_state_wingcc( pls, PLSTATE_COLOR0 );
627  //
628  // Display the window which we just created (using the nShow
629  // passed by the OS, which allows for start minimized and that
630  // sort of thing).
631  //
632  ShowWindow( dev->hwnd, SW_SHOWDEFAULT );
633  SetForegroundWindow( dev->hwnd );
634 
635  //
636  // Set up the DPI etc...
637  //
638 
639 
640  if ( pls->xdpi <= 0 ) // Get DPI from windows
641  {
642  plspage( GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4,
643  GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4, 0, 0, 0, 0 );
644  }
645  else
646  {
647  pls->ydpi = pls->xdpi; // Set X and Y dpi's to the same value
648  }
649 
650 
651 //
652 // Now we have to find out, from windows, just how big our drawing area is
653 // when we specified the page size earlier on, that includes the borders,
654 // title bar etc... so now that windows has done all its initialisations,
655 // we will ask how big the drawing area is, and tell plplot
656 //
657 
658  GetClientRect( dev->hwnd, &dev->rect );
659  dev->width = dev->rect.right;
660  dev->height = dev->rect.bottom;
661 
662  if ( dev->width > dev->height ) // Work out the scaling factor for the
663  { // "virtual" (oversized) page
664  dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
665  }
666  else
667  {
668  dev->scale = (PLFLT) PIXELS_Y / dev->height;
669  }
670 
671  Debug2( "Scale = %f (FLT)\n", dev->scale );
672 
673  plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
674  plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) );
675 
676  // Set fill rule.
677  if ( pls->dev_eofill )
678  SetPolyFillMode( dev->hdc, ALTERNATE );
679  else
680  SetPolyFillMode( dev->hdc, WINDING );
681 
682 #ifdef PL_HAVE_FREETYPE
683  if ( pls->dev_text )
684  {
685  init_freetype_lv2( pls );
686  }
687 #endif
688 }
689 
690 //--------------------------------------------------------------------------
691 // plD_line_wingcc()
692 //
693 // Draw a line in the current color from (x1,y1) to (x2,y2).
694 //--------------------------------------------------------------------------
695 
696 void
697 plD_line_wingcc( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
698 {
699  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
700  POINT points[2];
701 
702 
703  points[0].x = (LONG) ( x1a / dev->scale );
704  points[1].x = (LONG) ( x2a / dev->scale );
705  points[0].y = (LONG) ( dev->height - ( y1a / dev->scale ) );
706  points[1].y = (LONG) ( dev->height - ( y2a / dev->scale ) );
707 
708  dev->oldobject = SelectObject( dev->hdc, dev->pen );
709 
710  if ( points[0].x != points[1].x || points[0].y != points[1].y )
711  {
712  Polyline( dev->hdc, points, 2 );
713  }
714  else
715  {
716  SetPixel( dev->hdc, points[0].x, points[0].y, dev->colour );
717  }
718  SelectObject( dev->hdc, dev->oldobject );
719 }
720 
721 
722 //--------------------------------------------------------------------------
723 // plD_polyline_wingcc()
724 //
725 // Draw a polyline in the current color.
726 //--------------------------------------------------------------------------
727 
728 void
729 plD_polyline_wingcc( PLStream *pls, short *xa, short *ya, PLINT npts )
730 {
731  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
732  int i;
733  POINT *points = NULL;
734 
735  if ( npts > 0 )
736  {
737  points = GlobalAlloc( GMEM_ZEROINIT | GMEM_FIXED, (size_t) npts * sizeof ( POINT ) );
738  if ( points != NULL )
739  {
740  for ( i = 0; i < npts; i++ )
741  {
742  points[i].x = (LONG) ( xa[i] / dev->scale );
743  points[i].y = (LONG) ( dev->height - ( ya[i] / dev->scale ) );
744  }
745  dev->oldobject = SelectObject( dev->hdc, dev->pen );
746  Polyline( dev->hdc, points, npts );
747  SelectObject( dev->hdc, dev->oldobject );
748  GlobalFree( points );
749  }
750  else
751  {
752  plexit( "Could not allocate memory to \"plD_polyline_wingcc\"\n" );
753  }
754  }
755 }
756 
757 //--------------------------------------------------------------------------
758 // plD_fill_polygon_wingcc()
759 //
760 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
761 //--------------------------------------------------------------------------
762 
763 static void
764 plD_fill_polygon_wingcc( PLStream *pls )
765 {
766  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
767  int i;
768  POINT *points = NULL;
769  HPEN hpen, hpenOld;
770 
771  if ( pls->dev_npts > 0 )
772  {
773  points = GlobalAlloc( GMEM_ZEROINIT, (size_t) pls->dev_npts * sizeof ( POINT ) );
774 
775  if ( points == NULL )
776  plexit( "Could not allocate memory to \"plD_fill_polygon_wingcc\"\n" );
777 
778  for ( i = 0; i < pls->dev_npts; i++ )
779  {
780  points[i].x = (PLINT) ( pls->dev_x[i] / dev->scale );
781  points[i].y = (PLINT) ( dev->height - ( pls->dev_y[i] / dev->scale ) );
782  }
783 
784  dev->fillbrush = CreateSolidBrush( dev->colour );
785  hpen = CreatePen( PS_SOLID, 1, dev->colour );
786  dev->oldobject = SelectObject( dev->hdc, dev->fillbrush );
787  hpenOld = SelectObject( dev->hdc, hpen );
788  Polygon( dev->hdc, points, pls->dev_npts );
789  SelectObject( dev->hdc, dev->oldobject );
790  DeleteObject( dev->fillbrush );
791  SelectObject( dev->hdc, hpenOld );
792  DeleteObject( hpen );
793  GlobalFree( points );
794  }
795 }
796 
797 //--------------------------------------------------------------------------
798 // static void CopySCRtoBMP(PLStream *pls)
799 // Function copies the screen contents into a bitmap which is
800 // later used for fast redraws of the screen (when it gets corrupted)
801 // rather than remaking the plot from the plot buffer.
802 //--------------------------------------------------------------------------
803 
804 static void CopySCRtoBMP( PLStream *pls )
805 {
806  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
807 
808  //
809  // Clean up the old bitmap and DC
810  //
811 
812  if ( dev->hdc2 != NULL )
813  DeleteDC( dev->hdc2 );
814  if ( dev->bitmap != NULL )
815  DeleteObject( dev->bitmap );
816 
817  dev->hdc2 = CreateCompatibleDC( dev->hdc );
818  GetClientRect( dev->hwnd, &dev->rect );
819  dev->bitmap = CreateCompatibleBitmap( dev->hdc, dev->rect.right, dev->rect.bottom );
820  dev->oldobject = SelectObject( dev->hdc2, dev->bitmap );
821  BitBlt( dev->hdc2, 0, 0, dev->rect.right, dev->rect.bottom, dev->hdc, 0, 0, SRCCOPY );
822  SelectObject( dev->hdc2, dev->oldobject );
823 }
824 
825 
826 
827 void
828 plD_eop_wingcc( PLStream *pls )
829 {
830  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
831 
832  Debug( "End of the page\n" );
833  CopySCRtoBMP( pls );
834  dev->already_erased = 2;
835 
836  NormalCursor();
837 
838  if ( !pls->nopause )
839  {
840  dev->waiting = 1;
841  while ( GetMessage( &dev->msg, NULL, 0, 0 ) )
842  {
843  TranslateMessage( &dev->msg );
844  switch ( (int) dev->msg.message )
845  {
846  case WM_CONTEXTMENU:
847  case WM_RBUTTONDOWN:
848  TrackPopupMenu( dev->PopupMenu, TPM_CENTERALIGN | TPM_RIGHTBUTTON, LOWORD( dev->msg.lParam ),
849  HIWORD( dev->msg.lParam ), 0, dev->hwnd, NULL );
850  break;
851 
852  case WM_CHAR:
853  if ( ( (TCHAR) ( dev->msg.wParam ) == 32 ) ||
854  ( (TCHAR) ( dev->msg.wParam ) == 13 ) )
855  {
856  dev->waiting = 0;
857  }
858  else if ( ( (TCHAR) ( dev->msg.wParam ) == 27 ) ||
859  ( (TCHAR) ( dev->msg.wParam ) == 'q' ) ||
860  ( (TCHAR) ( dev->msg.wParam ) == 'Q' ) )
861  {
862  dev->waiting = 0;
863  PostQuitMessage( 0 );
864  }
865  break;
866 
867  case WM_LBUTTONDBLCLK:
868  Debug( "WM_LBUTTONDBLCLK\t" );
869  dev->waiting = 0;
870  break;
871 
872  case WM_COMMAND:
873  switch ( LOWORD( dev->msg.wParam ) )
874  {
875  case PopupPrint:
876  Debug( "PopupPrint" );
877  PrintPage( pls );
878  break;
879  case PopupNextPage:
880  Debug( "PopupNextPage" );
881  dev->waiting = 0;
882  break;
883  case PopupQuit:
884  Debug( "PopupQuit" );
885  dev->waiting = 0;
886  PostQuitMessage( 0 );
887  break;
888  }
889  break;
890 
891  default:
892  DispatchMessage( &dev->msg );
893  break;
894  }
895  if ( dev->waiting == 0 )
896  break;
897  }
898  }
899 }
900 
901 //--------------------------------------------------------------------------
902 // Beginning of the new page
903 //--------------------------------------------------------------------------
904 void
905 plD_bop_wingcc( PLStream *pls )
906 {
907  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
908 #ifdef PL_HAVE_FREETYPE
909  FT_Data *FT = (FT_Data *) pls->FT;
910 #endif
911  Debug( "Start of Page\t" );
912 
913 //
914 // Turn the cursor to a busy sign, clear the page by "invalidating" it
915 // then reset the colours and pen width
916 //
917 
918  BusyCursor();
919  dev->already_erased = 0;
920  RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
921 
922  plD_state_wingcc( pls, PLSTATE_COLOR0 );
923 }
924 
925 void
926 plD_tidy_wingcc( PLStream *pls )
927 {
928  wingcc_Dev *dev = NULL;
929 
930 #ifdef PL_HAVE_FREETYPE
931  if ( pls->dev_text )
932  {
933  FT_Data *FT = (FT_Data *) pls->FT;
934  plscmap0n( FT->ncol0_org );
935  plD_FreeType_Destroy( pls );
936  }
937 #endif
938  Debug( "plD_tidy_wingcc" );
939 
940  if ( pls->dev != NULL )
941  {
942  dev = (wingcc_Dev *) pls->dev;
943 
944  DeleteMenu( dev->PopupMenu, PopupPrint, 0 );
945  DeleteMenu( dev->PopupMenu, PopupNextPage, 0 );
946  DeleteMenu( dev->PopupMenu, PopupQuit, 0 );
947  DestroyMenu( dev->PopupMenu );
948 
949  if ( dev->hdc2 != NULL )
950  DeleteDC( dev->hdc2 );
951  if ( dev->hdc != NULL )
952  ReleaseDC( dev->hwnd, dev->hdc );
953  if ( dev->bitmap != NULL )
954  DeleteObject( dev->bitmap );
955 
956  free_mem( pls->dev );
957  }
958 }
959 
960 
961 
962 
963 //--------------------------------------------------------------------------
964 // plD_state_png()
965 //
966 // Handle change in PLStream state (color, pen width, fill attribute, etc).
967 //--------------------------------------------------------------------------
968 
969 void
970 plD_state_wingcc( PLStream *pls, PLINT op )
971 {
972  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
973 
974  switch ( op )
975  {
976  case PLSTATE_COLOR0:
977  case PLSTATE_COLOR1:
978  dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b );
979  break;
980 
981  case PLSTATE_CMAP0:
982  case PLSTATE_CMAP1:
983  dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b );
984 
985 
986  break;
987  }
988 
989  if ( dev->pen != NULL )
990  DeleteObject( dev->pen );
991  dev->pen = CreatePen( PS_SOLID, pls->width, dev->colour );
992 }
993 
994 void
995 plD_esc_wingcc( PLStream *pls, PLINT op, void *ptr )
996 {
997  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
998 
999  switch ( op )
1000  {
1001  case PLESC_GETC:
1002  break;
1003 
1004  case PLESC_FILL:
1005  plD_fill_polygon_wingcc( pls );
1006  break;
1007 
1008  case PLESC_DOUBLEBUFFERING:
1009  break;
1010 
1011  case PLESC_XORMOD:
1012  if ( *(PLINT *) ( ptr ) == 0 )
1013  SetROP2( dev->hdc, R2_COPYPEN );
1014  else
1015  SetROP2( dev->hdc, R2_XORPEN );
1016  break;
1017 
1018 #ifdef PL_HAVE_FREETYPE
1019  case PLESC_HAS_TEXT:
1020  plD_render_freetype_text( pls, (EscText *) ptr );
1021  break;
1022 
1023 // case PLESC_LIKES_UNICODE:
1024 // plD_render_freetype_sym(pls, (EscText *)ptr);
1025 // break;
1026 
1027 #endif
1028  }
1029 }
1030 
1031 //--------------------------------------------------------------------------
1032 // static void Resize( PLStream *pls )
1033 //
1034 // This function calculates how to resize a window after a message has been
1035 // received from windows telling us the window has been changed.
1036 // It tries to recalculate the scale of the window so everything works out
1037 // just right.
1038 // The window is only resized if plplot has finished all of its plotting.
1039 // That means that if you resize while a picture is being plotted,
1040 // unpredictable results may result. The reason I do this is because the
1041 // resize function calls redraw window, which replays the whole plot.
1042 //--------------------------------------------------------------------------
1043 
1044 static void Resize( PLStream *pls )
1045 {
1046  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1047 #ifdef PL_HAVE_FREETYPE
1048  FT_Data *FT = (FT_Data *) pls->FT;
1049 #endif
1050  Debug( "Resizing" );
1051 
1052  if ( dev->waiting == 1 ) // Only resize the window IF plplot has finished with it
1053  {
1054  memcpy( &dev->oldrect, &dev->rect, sizeof ( RECT ) );
1055  GetClientRect( dev->hwnd, &dev->rect );
1056  Debug3( "[%d %d]", dev->rect.right, dev->rect.bottom );
1057 
1058  if ( ( dev->rect.right > 0 ) && ( dev->rect.bottom > 0 ) ) // Check to make sure it isn't just minimised (i.e. zero size)
1059  {
1060  if ( memcmp( &dev->rect, &dev->oldrect, sizeof ( RECT ) ) != 0 ) // See if the window's changed size or not
1061  {
1062  dev->already_erased = 0;
1063  dev->width = dev->rect.right;
1064  dev->height = dev->rect.bottom;
1065  if ( dev->width > dev->height ) // Work out the scaling factor for the
1066  { // "virtual" (oversized) page
1067  dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
1068  }
1069  else
1070  {
1071  dev->scale = (PLFLT) PIXELS_Y / dev->height;
1072  }
1073 
1074 #ifdef PL_HAVE_FREETYPE
1075  if ( FT )
1076  {
1077  FT->scale = dev->scale;
1078  FT->ymax = dev->height;
1079  }
1080 #endif
1081  }
1082  RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
1083  }
1084  else
1085  {
1086  memcpy( &dev->rect, &dev->oldrect, sizeof ( RECT ) ); // restore the old size to current size since the window is minimised
1087  }
1088  }
1089 }
1090 
1091 
1092 //--------------------------------------------------------------------------
1093 // int SetRegValue(char *key_name, char *key_word, char *buffer,int dwType, int size)
1094 //
1095 // Function set the registry; if registary entry does not exist, it is
1096 // created. Actually, the key is created before it is set just to make sure
1097 // that is is there !
1098 //--------------------------------------------------------------------------
1099 
1100 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size )
1101 {
1102  int j = 0;
1103 
1104  DWORD lpdwDisposition;
1105  HKEY hKey;
1106 
1107  j = RegCreateKeyEx(
1108  HKEY_CURRENT_USER,
1109  key_name,
1110  0, // reserved
1111  NULL, // address of class string
1112  REG_OPTION_NON_VOLATILE, // special options flag
1113  KEY_WRITE, // desired security access
1114  NULL, // address of key security structure
1115  &hKey, // address of buffer for opened handle
1116  &lpdwDisposition // address of disposition value buffer
1117  );
1118 
1119  if ( j == ERROR_SUCCESS )
1120  {
1121  RegSetValueEx( hKey, key_word, 0, dwType, buffer, size );
1122  RegCloseKey( hKey );
1123  }
1124  return ( j );
1125 }
1126 
1127 //--------------------------------------------------------------------------
1128 // int GetRegValue(char *key_name, char *key_word, char *buffer, int size)
1129 //
1130 // Function reads the registry and gets a string value from it
1131 // buffer must be allocated by the caller, and the size is given in the size
1132 // paramater.
1133 // Return code is 1 for success, and 0 for failure.
1134 //--------------------------------------------------------------------------
1135 
1136 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size )
1137 {
1138  int ret = 0;
1139  HKEY hKey;
1140  int dwType;
1141  int dwSize = size;
1142 
1143  if ( RegOpenKeyEx( HKEY_CURRENT_USER, key_name, 0, KEY_READ, &hKey ) == ERROR_SUCCESS )
1144  {
1145  if ( RegQueryValueEx( hKey, key_word, 0, (LPDWORD) &dwType, buffer, (LPDWORD) &dwSize ) == ERROR_SUCCESS )
1146  {
1147  ret = 1;
1148  }
1149  RegCloseKey( hKey );
1150  }
1151  return ( ret );
1152 }
1153 
1154 #ifdef PL_HAVE_FREETYPE
1155 
1156 //--------------------------------------------------------------------------
1157 // void plD_pixel_wingcc (PLStream *pls, short x, short y)
1158 //
1159 // callback function, of type "plD_pixel_fp", which specifies how a single
1160 // pixel is set in the current colour.
1161 //--------------------------------------------------------------------------
1162 
1163 static void plD_pixel_wingcc( PLStream *pls, short x, short y )
1164 {
1165  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1166 
1167  SetPixel( dev->hdc, x, y, dev->colour );
1168 }
1169 
1170 static void plD_pixelV_wingcc( PLStream *pls, short x, short y )
1171 {
1172  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1173 
1174  SetPixelV( dev->hdc, x, y, dev->colour );
1175 }
1176 
1177 //--------------------------------------------------------------------------
1178 // void plD_set_pixelV_wingcc (PLStream *pls, short x, short y,PLINT colour)
1179 //
1180 // callback function, of type "plD_set_pixel_fp", which specifies how a
1181 // single pixel is set in the s[ecified colour. This colour
1182 // by-passes plplot's internal table, and directly 'hits the hardware'.
1183 //--------------------------------------------------------------------------
1184 
1185 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour )
1186 {
1187  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1188 
1189  SetPixel( dev->hdc, x, y, colour );
1190 }
1191 
1192 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour )
1193 {
1194  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1195 
1196  SetPixelV( dev->hdc, x, y, colour );
1197 }
1198 
1199 
1200 //--------------------------------------------------------------------------
1201 // void plD_read_pixel_wingcc (PLStream *pls, short x, short y)
1202 //
1203 // callback function, of type "plD_pixel_fp", which specifies how a single
1204 // pixel is read.
1205 //--------------------------------------------------------------------------
1206 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y )
1207 {
1208  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1209 
1210  return ( GetPixel( dev->hdc, x, y ) );
1211 }
1212 
1213 
1214 //--------------------------------------------------------------------------
1215 // void init_freetype_lv1 (PLStream *pls)
1216 //
1217 // "level 1" initialisation of the freetype library.
1218 // "Level 1" initialisation calls plD_FreeType_init(pls) which allocates
1219 // memory to the pls->FT structure, then sets up the pixel callback
1220 // function.
1221 //--------------------------------------------------------------------------
1222 
1223 static void init_freetype_lv1( PLStream *pls )
1224 {
1225  FT_Data *FT;
1226  int x;
1227  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1228 
1229  plD_FreeType_init( pls );
1230 
1231  FT = (FT_Data *) pls->FT;
1232 
1233 
1234 
1235 //
1236 // Work out if our device support "fast" pixel setting
1237 // and if so, use that instead of "slow" pixel setting
1238 //
1239 
1240  x = GetDeviceCaps( dev->hdc, RASTERCAPS );
1241 
1242  if ( x & RC_BITBLT )
1243  FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
1244  else
1245  FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
1246 
1247 //
1248 // See if we have a 24 bit device (or better), in which case
1249 // we can use the better antialaaising.
1250 //
1251 
1252  if ( GetDeviceCaps( dev->hdc, BITSPIXEL ) > 24 )
1253  {
1254  FT->BLENDED_ANTIALIASING = 1;
1255  FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_wingcc;
1256 
1257  if ( x & RC_BITBLT )
1258  FT->set_pixel = (plD_set_pixel_fp) plD_set_pixelV_wingcc;
1259  else
1260  FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_wingcc;
1261  }
1262 }
1263 
1264 //--------------------------------------------------------------------------
1265 // void init_freetype_lv2 (PLStream *pls)
1266 //
1267 // "Level 2" initialisation of the freetype library.
1268 // "Level 2" fills in a few setting that aren't public until after the
1269 // graphics sub-system has been initialised.
1270 // The "level 2" initialisation fills in a few things that are defined
1271 // later in the initialisation process for the GD driver.
1272 //
1273 // FT->scale is a scaling factor to convert co-ordinates. This is used by
1274 // the GD and other drivers to scale back a larger virtual page and this
1275 // eliminate the "hidden line removal bug". Set it to 1 if your device
1276 // doesn't have scaling.
1277 //
1278 // Some coordinate systems have zero on the bottom, others have zero on
1279 // the top. Freetype does it one way, and most everything else does it the
1280 // other. To make sure everything is working ok, we have to "flip" the
1281 // coordinates, and to do this we need to know how big in the Y dimension
1282 // the page is, and whether we have to invert the page or leave it alone.
1283 //
1284 // FT->ymax specifies the size of the page FT->invert_y=1 tells us to
1285 // invert the y-coordinates, FT->invert_y=0 will not invert the
1286 // coordinates.
1287 //--------------------------------------------------------------------------
1288 
1289 static void init_freetype_lv2( PLStream *pls )
1290 {
1291  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1292  FT_Data *FT = (FT_Data *) pls->FT;
1293 
1294  FT->scale = dev->scale;
1295  FT->ymax = dev->height;
1296  FT->invert_y = 1;
1297 
1298  if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) ) // do we want to at least *try* for smoothing ?
1299  {
1300  FT->ncol0_org = pls->ncol0; // save a copy of the original size of ncol0
1301  FT->ncol0_xtra = 16777216 - ( pls->ncol1 + pls->ncol0 ); // work out how many free slots we have
1302  FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // find out how many different shades of anti-aliasing we can do
1303  FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // set a maximum number of shades
1304  plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) ); // redefine the size of cmap0
1305 // the level manipulations are to turn off the plP_state(PLSTATE_CMAP0)
1306 // call in plscmap0 which (a) leads to segfaults since the GD image is
1307 // not defined at this point and (b) would be inefficient in any case since
1308 // setcmap is always called later (see plD_bop_png) to update the driver
1309 // color palette to be consistent with cmap0.
1310  {
1311  PLINT level_save;
1312  level_save = pls->level;
1313  pls->level = 0;
1314  pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); // call the function to add the extra cmap0 entries and calculate stuff
1315  pls->level = level_save;
1316  }
1317  FT->smooth_text = 1; // Yippee ! We had success setting up the extended cmap0
1318  }
1319  else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) ) // If we have a truecolour device, we wont even bother trying to change the palette
1320  {
1321  FT->smooth_text = 1;
1322  }
1323 }
1324 #endif
1325 
1326 //--------------------------------------------------------------------------
1327 // static void UpdatePageMetrics ( PLStream *pls, char flag )
1328 //
1329 // UpdatePageMetrics is a simple function which simply gets new vales for
1330 // a changed DC, be it swapping from printer to screen or vice-versa.
1331 // The flag variable is used to tell the function if it is updating
1332 // from the printer (1) or screen (0).
1333 //--------------------------------------------------------------------------
1334 
1335 static void UpdatePageMetrics( PLStream *pls, char flag )
1336 {
1337  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1338  #ifdef PL_HAVE_FREETYPE
1339  FT_Data *FT = (FT_Data *) pls->FT;
1340  #endif
1341 
1342  if ( flag == 1 )
1343  {
1344  dev->width = GetDeviceCaps( dev->hdc, HORZRES ); // Get the page size from the printer
1345  dev->height = GetDeviceCaps( dev->hdc, VERTRES );
1346  }
1347  else
1348  {
1349  GetClientRect( dev->hwnd, &dev->rect );
1350  dev->width = dev->rect.right;
1351  dev->height = dev->rect.bottom;
1352  }
1353 
1354  if ( dev->width > dev->height ) // Work out the scaling factor for the
1355  { // "virtual" (oversized) page
1356  dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
1357  }
1358  else
1359  {
1360  dev->scale = (PLFLT) PIXELS_Y / dev->height;
1361  }
1362 
1363  #ifdef PL_HAVE_FREETYPE
1364  if ( FT ) // If we are using freetype, then set it up next
1365  {
1366  FT->scale = dev->scale;
1367  FT->ymax = dev->height;
1368  if ( GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_BITBLT )
1369  FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
1370  else
1371  FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
1372  }
1373  #endif
1374 
1375  pls->xdpi = GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4;
1376  pls->ydpi = GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4;
1377  plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
1378  plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) );
1379 }
1380 
1381 //--------------------------------------------------------------------------
1382 // static void PrintPage ( PLStream *pls )
1383 //
1384 // Function brings up a standard printer dialog and, after the user
1385 // has selected a printer, replots the current page to the windows
1386 // printer.
1387 //--------------------------------------------------------------------------
1388 
1389 static void PrintPage( PLStream *pls )
1390 {
1391  wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1392  #ifdef PL_HAVE_FREETYPE
1393  FT_Data *FT = (FT_Data *) pls->FT;
1394  #endif
1395  PRINTDLG Printer;
1396  DOCINFO docinfo;
1397 
1398  //
1399  // Reset the docinfo structure to 0 and set it's fields up
1400  // This structure is used to supply a name to the print queue
1401  //
1402 
1403  ZeroMemory( &docinfo, sizeof ( docinfo ) );
1404  docinfo.cbSize = sizeof ( docinfo );
1405  docinfo.lpszDocName = _T( "Plplot Page" );
1406 
1407  //
1408  // Reset out printer structure to zero and initialise it
1409  //
1410 
1411  ZeroMemory( &Printer, sizeof ( PRINTDLG ) );
1412  Printer.lStructSize = sizeof ( PRINTDLG );
1413  Printer.hwndOwner = dev->hwnd;
1414  Printer.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
1415  Printer.nCopies = 1;
1416 
1417  //
1418  // Call the printer dialog function.
1419  // If the user has clicked on "Print", then we will continue
1420  // processing and print out the page.
1421  //
1422 
1423  if ( PrintDlg( &Printer ) != 0 )
1424  {
1425  //
1426  // Before doing anything, we will take some backup copies
1427  // of the existing values for page size and the like, because
1428  // all we are going to do is a quick and dirty modification
1429  // of plplot's internals to match the new page size and hope
1430  // it all works out ok. After that, we will manip the values,
1431  // and when all is done, restore them.
1432  //
1433 
1434  if ( ( dev->push = GlobalAlloc( GMEM_ZEROINIT, sizeof ( wingcc_Dev ) ) ) != NULL )
1435  {
1436  BusyCursor();
1437  memcpy( dev->push, dev, sizeof ( wingcc_Dev ) );
1438 
1439  dev->hdc = dev->PRNT_hdc = Printer.hDC; // Copy the printer HDC
1440 
1441  UpdatePageMetrics( pls, 1 );
1442 
1443  #ifdef PL_HAVE_FREETYPE
1444  if ( FT ) // If we are using freetype, then set it up next
1445  {
1446  dev->FT_smooth_text = FT->smooth_text; // When printing, we don't want smoothing
1447  FT->smooth_text = 0;
1448  }
1449  #endif
1450 
1451  //
1452  // Now the stuff that actually does the printing !!
1453  //
1454 
1455  StartDoc( dev->hdc, &docinfo );
1456  plRemakePlot( pls );
1457  EndDoc( dev->hdc );
1458 
1459  //
1460  // Now to undo everything back to what it was for the screen
1461  //
1462 
1463  dev->hdc = dev->SCRN_hdc; // Reset the screen HDC to the default
1464  UpdatePageMetrics( pls, 0 );
1465 
1466  #ifdef PL_HAVE_FREETYPE
1467  if ( FT ) // If we are using freetype, then set it up next
1468  {
1469  FT->smooth_text = dev->FT_smooth_text;
1470  }
1471  #endif
1472  memcpy( dev, dev->push, sizeof ( wingcc_Dev ) ); // POP our "stack" now to restore the values
1473 
1474  GlobalFree( dev->push );
1475  NormalCursor();
1476  RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
1477  }
1478  }
1479 }
1480 
1481 
1482 
1483 #else
1484 int
1486 {
1487  return ( 0 );
1488 }
1489 
1490 #endif // PLD_wingccdev
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1412
#define PLSTATE_CMAP0
Definition: plplotP.h:333
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:70
#define PLESC_XORMOD
Definition: plplot.h:226
#define plspage
Definition: plplot.h:723
PLINT level
Definition: plstrm.h:533
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:72
unsigned char b
Definition: plplot.h:455
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:75
#define PLESC_FILL
Definition: plplot.h:219
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:74
#define PLESC_DOUBLEBUFFERING
Definition: plplot.h:225
plD_esc_fp pl_esc
Definition: disptab.h:91
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wingcc(PLDispatchTable *pdt)
PLFLT xdpi
Definition: plstrm.h:619
PLINT dev_text
Definition: plstrm.h:577
PLINT dev_npts
Definition: plstrm.h:586
const char * pl_MenuStr
Definition: disptab.h:80
PLINT color
Definition: plstrm.h:574
PLINT dev_unicode
Definition: plstrm.h:754
plD_tidy_fp pl_tidy
Definition: disptab.h:89
PLINT plbuf_write
Definition: plstrm.h:572
PLINT dev_clear
Definition: plstrm.h:577
void PLFLT PLINT PLINT PLFLT x
const char * pl_DevName
Definition: disptab.h:81
#define PLSTATE_COLOR0
Definition: plplotP.h:330
plD_init_fp pl_init
Definition: disptab.h:84
PLINT colorset
Definition: plstrm.h:574
char * program
Definition: plstrm.h:536
#define PLSTATE_COLOR1
Definition: plplotP.h:331
#define max_number_of_grey_levels_used_in_text_smoothing
Definition: wxwidgets.h:34
short * dev_x
Definition: plstrm.h:587
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:71
int PLINT
Definition: plplot.h:175
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:76
static const char * program
Definition: plargs.c:172
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:73
PLINT ncol0
Definition: plstrm.h:545
unsigned char g
Definition: plplot.h:454
PLINT termin
Definition: plstrm.h:573
#define PLSTATE_CMAP1
Definition: plplotP.h:334
PLStream * pls[]
PLINT icol0
Definition: plstrm.h:545
#define PIXELS_X
Definition: plplotP.h:309
#define TRUE
Definition: plplotP.h:181
PLINT ylength
Definition: plstrm.h:620
void PLFLT PLINT PLINT PLFLT PLFLT y
plD_bop_fp pl_bop
Definition: disptab.h:88
plD_line_fp pl_line
Definition: disptab.h:85
static PLINT * buffer
Definition: plfill.c:76
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4072
PLColor * cmap0
Definition: plstrm.h:550
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:66
PLINT dev_xor
Definition: plstrm.h:577
PLFLT ydpi
Definition: plstrm.h:619
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4083
PLINT xlength
Definition: plstrm.h:620
#define PL_HAVE_FREETYPE
Definition: config.h:55
PLINT yoffset
Definition: plstrm.h:621
int pldummy_wingcc()
Definition: wingcc.c:1485
short * dev_y
Definition: plstrm.h:587
#define PIXELS_Y
Definition: plplotP.h:310
void plRemakePlot(PLStream *pls)
Definition: plbuf.c:957
float PLFLT
Definition: plplot.h:159
PLINT graphx
Definition: plstrm.h:573
#define free_mem(a)
Definition: plplotP.h:187
unsigned char r
Definition: plplot.h:453
#define PLESC_HAS_TEXT
Definition: plplot.h:230
PLINT nopause
Definition: plstrm.h:573
PLFLT width
Definition: plstrm.h:557
#define plscmap0n
Definition: plplot.h:686
PLINT dev_dash
Definition: plstrm.h:576
PLColor curcolor
Definition: plstrm.h:549
plD_state_fp pl_state
Definition: disptab.h:90
plD_eop_fp pl_eop
Definition: disptab.h:87
PLINT xoffset
Definition: plstrm.h:621
PLINT ncol1
Definition: plstrm.h:545
#define PLESC_GETC
Definition: plplot.h:223
plD_polyline_fp pl_polyline
Definition: disptab.h:86
void * dev
Definition: plstrm.h:599
void * FT
Definition: plstrm.h:746
PLINT dev_fill0
Definition: plstrm.h:576
PLINT dev_eofill
Definition: plstrm.h:795
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:69
#define GRAPHICS_MODE
Definition: plplotP.h:293
void plexit(const char *errormsg)
Definition: plctrl.c:1941