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