PLplot: wingcc.c Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
wingcc.c
Go to the documentation of this file.
1 // $Id: wingcc.c 12965 2014-01-28 20:23: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
126 void plD_dispatch_init_wingcc( PLDispatchTable *pdt );
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
217 void plD_dispatch_init_wingcc( PLDispatchTable *pdt )
218 {
219 #ifndef ENABLE_DYNDRIVERS
220 pdt->pl_MenuStr = "Win32 GCC device";
221 pdt->pl_DevName = "wingcc";
222 #endif
223 pdt->pl_type = plDevType_Interactive;
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 break;
985 }
986
987 if ( dev->pen != NULL )
988 DeleteObject( dev->pen );
989 dev->pen = CreatePen( PS_SOLID, pls->width, dev->colour );
990 }
991
992 void
993 plD_esc_wingcc( PLStream *pls, PLINT op, void *ptr )
994 {
995 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
996
997 switch ( op )
998 {
999 case PLESC_GETC:
1000 break;
1001
1002 case PLESC_FILL:
1003 plD_fill_polygon_wingcc( pls );
1004 break;
1005
1006 case PLESC_DOUBLEBUFFERING:
1007 break;
1008
1009 case PLESC_XORMOD:
1010 if ( *(PLINT *) ( ptr ) == 0 )
1011 SetROP2( dev->hdc, R2_COPYPEN );
1012 else
1013 SetROP2( dev->hdc, R2_XORPEN );
1014 break;
1015
1016 #ifdef PL_HAVE_FREETYPE
1017 case PLESC_HAS_TEXT:
1018 plD_render_freetype_text( pls, (EscText *) ptr );
1019 break;
1020
1021 // case PLESC_LIKES_UNICODE:
1022 // plD_render_freetype_sym(pls, (EscText *)ptr);
1023 // break;
1024
1025 #endif
1026 }
1027 }
1028
1029 //--------------------------------------------------------------------------
1030 // static void Resize( PLStream *pls )
1031 //
1032 // This function calculates how to resize a window after a message has been
1033 // received from windows telling us the window has been changed.
1034 // It tries to recalculate the scale of the window so everything works out
1035 // just right.
1036 // The window is only resized if plplot has finished all of its plotting.
1037 // That means that if you resize while a picture is being plotted,
1038 // unpredictable results may result. The reason I do this is because the
1039 // resize function calls redraw window, which replays the whole plot.
1040 //--------------------------------------------------------------------------
1041
1042 static void Resize( PLStream *pls )
1043 {
1044 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1045 #ifdef PL_HAVE_FREETYPE
1046 FT_Data *FT = (FT_Data *) pls->FT;
1047 #endif
1048 Debug( "Resizing" );
1049
1050 if ( dev->waiting == 1 ) // Only resize the window IF plplot has finished with it
1051 {
1052 memcpy( &dev->oldrect, &dev->rect, sizeof ( RECT ) );
1053 GetClientRect( dev->hwnd, &dev->rect );
1054 Debug3( "[%d %d]", dev->rect.right, dev->rect.bottom );
1055
1056 if ( ( dev->rect.right > 0 ) && ( dev->rect.bottom > 0 ) ) // Check to make sure it isn't just minimised (i.e. zero size)
1057 {
1058 if ( memcmp( &dev->rect, &dev->oldrect, sizeof ( RECT ) ) != 0 ) // See if the window's changed size or not
1059 {
1060 dev->already_erased = 0;
1061 dev->width = dev->rect.right;
1062 dev->height = dev->rect.bottom;
1063 if ( dev->width > dev->height ) // Work out the scaling factor for the
1064 { // "virtual" (oversized) page
1065 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
1066 }
1067 else
1068 {
1069 dev->scale = (PLFLT) PIXELS_Y / dev->height;
1070 }
1071
1072 #ifdef PL_HAVE_FREETYPE
1073 if ( FT )
1074 {
1075 FT->scale = dev->scale;
1076 FT->ymax = dev->height;
1077 }
1078 #endif
1079 }
1080 RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
1081 }
1082 else
1083 {
1084 memcpy( &dev->rect, &dev->oldrect, sizeof ( RECT ) ); // restore the old size to current size since the window is minimised
1085 }
1086 }
1087 }
1088
1089
1090 //--------------------------------------------------------------------------
1091 // int SetRegValue(char *key_name, char *key_word, char *buffer,int dwType, int size)
1092 //
1093 // Function set the registry; if registary entry does not exist, it is
1094 // created. Actually, the key is created before it is set just to make sure
1095 // that is is there !
1096 //--------------------------------------------------------------------------
1097
1098 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size )
1099 {
1100 int j = 0;
1101
1102 DWORD lpdwDisposition;
1103 HKEY hKey;
1104
1105 j = RegCreateKeyEx(
1106 HKEY_CURRENT_USER,
1107 key_name,
1108 0, // reserved
1109 NULL, // address of class string
1110 REG_OPTION_NON_VOLATILE, // special options flag
1111 KEY_WRITE, // desired security access
1112 NULL, // address of key security structure
1113 &hKey, // address of buffer for opened handle
1114 &lpdwDisposition // address of disposition value buffer
1115 );
1116
1117 if ( j == ERROR_SUCCESS )
1118 {
1119 RegSetValueEx( hKey, key_word, 0, dwType, buffer, size );
1120 RegCloseKey( hKey );
1121 }
1122 return ( j );
1123 }
1124
1125 //--------------------------------------------------------------------------
1126 // int GetRegValue(char *key_name, char *key_word, char *buffer, int size)
1127 //
1128 // Function reads the registry and gets a string value from it
1129 // buffer must be allocated by the caller, and the size is given in the size
1130 // paramater.
1131 // Return code is 1 for success, and 0 for failure.
1132 //--------------------------------------------------------------------------
1133
1134 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size )
1135 {
1136 int ret = 0;
1137 HKEY hKey;
1138 int dwType;
1139 int dwSize = size;
1140
1141 if ( RegOpenKeyEx( HKEY_CURRENT_USER, key_name, 0, KEY_READ, &hKey ) == ERROR_SUCCESS )
1142 {
1143 if ( RegQueryValueEx( hKey, key_word, 0, (LPDWORD) &dwType, buffer, (LPDWORD) &dwSize ) == ERROR_SUCCESS )
1144 {
1145 ret = 1;
1146 }
1147 RegCloseKey( hKey );
1148 }
1149 return ( ret );
1150 }
1151
1152 #ifdef PL_HAVE_FREETYPE
1153
1154 //--------------------------------------------------------------------------
1155 // void plD_pixel_wingcc (PLStream *pls, short x, short y)
1156 //
1157 // callback function, of type "plD_pixel_fp", which specifies how a single
1158 // pixel is set in the current colour.
1159 //--------------------------------------------------------------------------
1160
1161 static void plD_pixel_wingcc( PLStream *pls, short x, short y )
1162 {
1163 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1164
1165 SetPixel( dev->hdc, x, y, dev->colour );
1166 }
1167
1168 static void plD_pixelV_wingcc( PLStream *pls, short x, short y )
1169 {
1170 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1171
1172 SetPixelV( dev->hdc, x, y, dev->colour );
1173 }
1174
1175 //--------------------------------------------------------------------------
1176 // void plD_set_pixelV_wingcc (PLStream *pls, short x, short y,PLINT colour)
1177 //
1178 // callback function, of type "plD_set_pixel_fp", which specifies how a
1179 // single pixel is set in the s[ecified colour. This colour
1180 // by-passes plplot's internal table, and directly 'hits the hardware'.
1181 //--------------------------------------------------------------------------
1182
1183 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour )
1184 {
1185 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1186
1187 SetPixel( dev->hdc, x, y, colour );
1188 }
1189
1190 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour )
1191 {
1192 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1193
1194 SetPixelV( dev->hdc, x, y, colour );
1195 }
1196
1197
1198 //--------------------------------------------------------------------------
1199 // void plD_read_pixel_wingcc (PLStream *pls, short x, short y)
1200 //
1201 // callback function, of type "plD_pixel_fp", which specifies how a single
1202 // pixel is read.
1203 //--------------------------------------------------------------------------
1204 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y )
1205 {
1206 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1207
1208 return ( GetPixel( dev->hdc, x, y ) );
1209 }
1210
1211
1212 //--------------------------------------------------------------------------
1213 // void init_freetype_lv1 (PLStream *pls)
1214 //
1215 // "level 1" initialisation of the freetype library.
1216 // "Level 1" initialisation calls plD_FreeType_init(pls) which allocates
1217 // memory to the pls->FT structure, then sets up the pixel callback
1218 // function.
1219 //--------------------------------------------------------------------------
1220
1221 static void init_freetype_lv1( PLStream *pls )
1222 {
1223 FT_Data *FT;
1224 int x;
1225 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1226
1227 plD_FreeType_init( pls );
1228
1229 FT = (FT_Data *) pls->FT;
1230
1231
1232
1233 //
1234 // Work out if our device support "fast" pixel setting
1235 // and if so, use that instead of "slow" pixel setting
1236 //
1237
1238 x = GetDeviceCaps( dev->hdc, RASTERCAPS );
1239
1240 if ( x & RC_BITBLT )
1241 FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
1242 else
1243 FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
1244
1245 //
1246 // See if we have a 24 bit device (or better), in which case
1247 // we can use the better antialaaising.
1248 //
1249
1250 if ( GetDeviceCaps( dev->hdc, BITSPIXEL ) > 24 )
1251 {
1252 FT->BLENDED_ANTIALIASING = 1;
1253 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_wingcc;
1254
1255 if ( x & RC_BITBLT )
1256 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixelV_wingcc;
1257 else
1258 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_wingcc;
1259 }
1260 }
1261
1262 //--------------------------------------------------------------------------
1263 // void init_freetype_lv2 (PLStream *pls)
1264 //
1265 // "Level 2" initialisation of the freetype library.
1266 // "Level 2" fills in a few setting that aren't public until after the
1267 // graphics sub-system has been initialised.
1268 // The "level 2" initialisation fills in a few things that are defined
1269 // later in the initialisation process for the GD driver.
1270 //
1271 // FT->scale is a scaling factor to convert co-ordinates. This is used by
1272 // the GD and other drivers to scale back a larger virtual page and this
1273 // eliminate the "hidden line removal bug". Set it to 1 if your device
1274 // doesn't have scaling.
1275 //
1276 // Some coordinate systems have zero on the bottom, others have zero on
1277 // the top. Freetype does it one way, and most everything else does it the
1278 // other. To make sure everything is working ok, we have to "flip" the
1279 // coordinates, and to do this we need to know how big in the Y dimension
1280 // the page is, and whether we have to invert the page or leave it alone.
1281 //
1282 // FT->ymax specifies the size of the page FT->invert_y=1 tells us to
1283 // invert the y-coordinates, FT->invert_y=0 will not invert the
1284 // coordinates.
1285 //--------------------------------------------------------------------------
1286
1287 static void init_freetype_lv2( PLStream *pls )
1288 {
1289 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1290 FT_Data *FT = (FT_Data *) pls->FT;
1291
1292 FT->scale = dev->scale;
1293 FT->ymax = dev->height;
1294 FT->invert_y = 1;
1295
1296 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) ) // do we want to at least *try* for smoothing ?
1297 {
1298 FT->ncol0_org = pls->ncol0; // save a copy of the original size of ncol0
1299 FT->ncol0_xtra = 16777216 - ( pls->ncol1 + pls->ncol0 ); // work out how many free slots we have
1300 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // find out how many different shades of anti-aliasing we can do
1301 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // set a maximum number of shades
1302 plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) ); // redefine the size of cmap0
1303 // the level manipulations are to turn off the plP_state(PLSTATE_CMAP0)
1304 // call in plscmap0 which (a) leads to segfaults since the GD image is
1305 // not defined at this point and (b) would be inefficient in any case since
1306 // setcmap is always called later (see plD_bop_png) to update the driver
1307 // color palette to be consistent with cmap0.
1308 {
1309 PLINT level_save;
1310 level_save = pls->level;
1311 pls->level = 0;
1312 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); // call the function to add the extra cmap0 entries and calculate stuff
1313 pls->level = level_save;
1314 }
1315 FT->smooth_text = 1; // Yippee ! We had success setting up the extended cmap0
1316 }
1317 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
1318 {
1319 FT->smooth_text = 1;
1320 }
1321 }
1322 #endif
1323
1324 //--------------------------------------------------------------------------
1325 // static void UpdatePageMetrics ( PLStream *pls, char flag )
1326 //
1327 // UpdatePageMetrics is a simple function which simply gets new vales for
1328 // a changed DC, be it swapping from printer to screen or vice-versa.
1329 // The flag variable is used to tell the function if it is updating
1330 // from the printer (1) or screen (0).
1331 //--------------------------------------------------------------------------
1332
1333 static void UpdatePageMetrics( PLStream *pls, char flag )
1334 {
1335 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1336 #ifdef PL_HAVE_FREETYPE
1337 FT_Data *FT = (FT_Data *) pls->FT;
1338 #endif
1339
1340 if ( flag == 1 )
1341 {
1342 dev->width = GetDeviceCaps( dev->hdc, HORZRES ); // Get the page size from the printer
1343 dev->height = GetDeviceCaps( dev->hdc, VERTRES );
1344 }
1345 else
1346 {
1347 GetClientRect( dev->hwnd, &dev->rect );
1348 dev->width = dev->rect.right;
1349 dev->height = dev->rect.bottom;
1350 }
1351
1352 if ( dev->width > dev->height ) // Work out the scaling factor for the
1353 { // "virtual" (oversized) page
1354 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
1355 }
1356 else
1357 {
1358 dev->scale = (PLFLT) PIXELS_Y / dev->height;
1359 }
1360
1361 #ifdef PL_HAVE_FREETYPE
1362 if ( FT ) // If we are using freetype, then set it up next
1363 {
1364 FT->scale = dev->scale;
1365 FT->ymax = dev->height;
1366 if ( GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_BITBLT )
1367 FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
1368 else
1369 FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
1370 }
1371 #endif
1372
1373 pls->xdpi = GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4;
1374 pls->ydpi = GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4;
1375 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
1376 plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) );
1377 }
1378
1379 //--------------------------------------------------------------------------
1380 // static void PrintPage ( PLStream *pls )
1381 //
1382 // Function brings up a standard printer dialog and, after the user
1383 // has selected a printer, replots the current page to the windows
1384 // printer.
1385 //--------------------------------------------------------------------------
1386
1387 static void PrintPage( PLStream *pls )
1388 {
1389 wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
1390 #ifdef PL_HAVE_FREETYPE
1391 FT_Data *FT = (FT_Data *) pls->FT;
1392 #endif
1393 PRINTDLG Printer;
1394 DOCINFO docinfo;
1395
1396 //
1397 // Reset the docinfo structure to 0 and set it's fields up
1398 // This structure is used to supply a name to the print queue
1399 //
1400
1401 ZeroMemory( &docinfo, sizeof ( docinfo ) );
1402 docinfo.cbSize = sizeof ( docinfo );
1403 docinfo.lpszDocName = _T( "Plplot Page" );
1404
1405 //
1406 // Reset out printer structure to zero and initialise it
1407 //
1408
1409 ZeroMemory( &Printer, sizeof ( PRINTDLG ) );
1410 Printer.lStructSize = sizeof ( PRINTDLG );
1411 Printer.hwndOwner = dev->hwnd;
1412 Printer.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
1413 Printer.nCopies = 1;
1414
1415 //
1416 // Call the printer dialog function.
1417 // If the user has clicked on "Print", then we will continue
1418 // processing and print out the page.
1419 //
1420
1421 if ( PrintDlg( &Printer ) != 0 )
1422 {
1423 //
1424 // Before doing anything, we will take some backup copies
1425 // of the existing values for page size and the like, because
1426 // all we are going to do is a quick and dirty modification
1427 // of plplot's internals to match the new page size and hope
1428 // it all works out ok. After that, we will manip the values,
1429 // and when all is done, restore them.
1430 //
1431
1432 if ( ( dev->push = GlobalAlloc( GMEM_ZEROINIT, sizeof ( wingcc_Dev ) ) ) != NULL )
1433 {
1434 BusyCursor();
1435 memcpy( dev->push, dev, sizeof ( wingcc_Dev ) );
1436
1437 dev->hdc = dev->PRNT_hdc = Printer.hDC; // Copy the printer HDC
1438
1439 UpdatePageMetrics( pls, 1 );
1440
1441 #ifdef PL_HAVE_FREETYPE
1442 if ( FT ) // If we are using freetype, then set it up next
1443 {
1444 dev->FT_smooth_text = FT->smooth_text; // When printing, we don't want smoothing
1445 FT->smooth_text = 0;
1446 }
1447 #endif
1448
1449 //
1450 // Now the stuff that actually does the printing !!
1451 //
1452
1453 StartDoc( dev->hdc, &docinfo );
1454 plRemakePlot( pls );
1455 EndDoc( dev->hdc );
1456
1457 //
1458 // Now to undo everything back to what it was for the screen
1459 //
1460
1461 dev->hdc = dev->SCRN_hdc; // Reset the screen HDC to the default
1462 UpdatePageMetrics( pls, 0 );
1463
1464 #ifdef PL_HAVE_FREETYPE
1465 if ( FT ) // If we are using freetype, then set it up next
1466 {
1467 FT->smooth_text = dev->FT_smooth_text;
1468 }
1469 #endif
1470 memcpy( dev, dev->push, sizeof ( wingcc_Dev ) ); // POP our "stack" now to restore the values
1471
1472 GlobalFree( dev->push );
1473 NormalCursor();
1474 RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
1475 }
1476 }
1477 }
1478
1479
1480
1481 #else
1482 int
1483 pldummy_wingcc()
1484 {
1485 return ( 0 );
1486 }
1487
1488 #endif // PLD_wingccdev