PLplot 5.15.0
Loading...
Searching...
No Matches
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
73PLDLLIMPEXP_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).
83typedef 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
132void plD_init_wingcc( PLStream * );
133void plD_line_wingcc( PLStream *, short, short, short, short );
134void plD_polyline_wingcc( PLStream *, short *, short *, PLINT );
135void plD_eop_wingcc( PLStream * );
136void plD_bop_wingcc( PLStream * );
137void plD_tidy_wingcc( PLStream * );
138void plD_wait_wingcc( PLStream * );
139void plD_state_wingcc( PLStream *, PLINT );
140void plD_esc_wingcc( PLStream *, PLINT, void * );
141
142#ifdef PL_HAVE_FREETYPE
143
144static void plD_pixel_wingcc( PLStream *pls, short x, short y );
145static void plD_pixelV_wingcc( PLStream *pls, short x, short y );
146static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y );
147static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour );
148static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour );
149static void init_freetype_lv1( PLStream *pls );
150static void init_freetype_lv2( PLStream *pls );
151
152#endif
153
154
155//--------------------------------------------------------------------------
156// Local Function definitions and function-like defines
157//--------------------------------------------------------------------------
158
159static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size );
160static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size );
161static void Resize( PLStream *pls );
162static void plD_fill_polygon_wingcc( PLStream *pls );
163static void CopySCRtoBMP( PLStream *pls );
164static void PrintPage( PLStream *pls );
165static 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
228 pdt->pl_type = plDevType_Interactive;
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
241static 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
250LRESULT 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
417void
418plD_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
702void
703plD_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
734void
735plD_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
769static void
770plD_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
810static 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
833void
834plD_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//--------------------------------------------------------------------------
848void
849plD_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
869void
870plD_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
904void
905plD_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
976void
977plD_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
1005static void
1006GetCursorCmd( 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
1071void
1072plD_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
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
1122static 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
1178static 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
1214static 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
1241static 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
1248static 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
1263static 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
1270static 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//--------------------------------------------------------------------------
1284static 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
1301static 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
1367static 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
1413static 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
1467static 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
1562int
1564{
1565 return ( 0 );
1566}
1567
1568#endif // PLD_wingccdev
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition disptab.h:68
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition disptab.h:72
void(* plD_bop_fp)(struct PLStream_struct *)
Definition disptab.h:71
void(* plD_wait_fp)(struct PLStream_struct *)
Definition disptab.h:75
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition disptab.h:73
void(* plD_eop_fp)(struct PLStream_struct *)
Definition disptab.h:70
@ plDevType_Interactive
Definition disptab.h:14
void(* plD_init_fp)(struct PLStream_struct *)
Definition disptab.h:67
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
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wingcc(PLDispatchTable *pdt)
int plParseDrvOpts(DrvOpt *acc_opt)
Definition plargs.c:1461
static PLCHAR_VECTOR program
Definition plargs.c:178
void plRemakePlot(PLStream *pls)
Definition plbuf.c:1397
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition plcore.c:4238
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition plcore.c:4249
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
void plGinInit(PLGraphicsIn *gin)
Definition plctrl.c:2887
void plexit(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1958
#define PLDLLIMPEXP_DRIVER
Definition pldll.h:81
static PLINT * buffer
Definition plfill.c:74
#define GRAPHICS_MODE
Definition plplotP.h:288
#define PIXELS_X
Definition plplotP.h:304
#define PLSTATE_CMAP0
Definition plplotP.h:366
#define PLSTATE_COLOR1
Definition plplotP.h:364
#define TRUE
Definition plplotP.h:176
#define PLSTATE_CMAP1
Definition plplotP.h:367
@ DRV_INT
Definition plplotP.h:758
#define PLSTATE_COLOR0
Definition plplotP.h:363
#define free_mem(a)
Definition plplotP.h:182
#define PIXELS_Y
Definition plplotP.h:305
#define PLESC_GETC
Definition plplot.h:283
#define PLESC_HAS_TEXT
Definition plplot.h:290
float PLFLT
Definition plplot.h:163
#define plscmap0n
Definition plplot.h:793
#define plspage
Definition plplot.h:831
#define PLESC_FILL
Definition plplot.h:279
#define PLESC_XORMOD
Definition plplot.h:286
int PLINT
Definition plplot.h:181
#define PLESC_DOUBLEBUFFERING
Definition plplot.h:285
int pldummy_wingcc()
Definition wingcc.c:1563