PLplot
5.10.0
|
00001 // PLplot WIN32 under GCC device driver. 00002 // 00003 // Copyright (C) 2004 Andrew Roach 00004 // 00005 // This file is part of PLplot. 00006 // 00007 // PLplot is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU Library General Public License as published 00009 // by the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // PLplot is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU Library General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Library General Public License 00018 // along with PLplot; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // 00022 #include "plDevs.h" 00023 00024 #ifdef PLD_wingcc 00025 00026 #include <string.h> 00027 #include <windows.h> 00028 #if !defined ( __CYGWIN__ ) 00029 #include <tchar.h> 00030 #else 00031 #include <winnt.h> 00032 #define _T( a ) __TEXT( a ) 00033 #endif 00034 #ifdef _WIN64 00035 #define GWL_USERDATA GWLP_USERDATA 00036 #define GCL_HCURSOR GCLP_HCURSOR 00037 #endif 00038 00039 #include "plplotP.h" 00040 #include "drivers.h" 00041 #include "plevent.h" 00042 00043 #ifdef PL_HAVE_FREETYPE 00044 00045 // 00046 // Freetype support has been added to the wingcc driver using the 00047 // plfreetype.c module, and implemented as a driver-specific optional extra 00048 // invoked via the -drvopt command line toggle. It uses the 00049 // "PLESC_HAS_TEXT" command for rendering within the driver. 00050 // 00051 // Freetype support is turned on/off at compile time by defining 00052 // "PL_HAVE_FREETYPE". 00053 // 00054 // To give the user some level of control over the fonts that are used, 00055 // environmental variables can be set to over-ride the definitions used by 00056 // the five default plplot fonts. 00057 // 00058 // Freetype rendering is used with the command line "-drvopt text". 00059 // Anti-aliased fonts can be used by issuing "-drvopt text,smooth" 00060 // 00061 00062 #include "plfreetype.h" 00063 00064 #ifndef max_number_of_grey_levels_used_in_text_smoothing 00065 #define max_number_of_grey_levels_used_in_text_smoothing 64 00066 #endif 00067 00068 #endif 00069 00070 00071 // Device info 00072 00073 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wingcc = "wingcc:Win32 (GCC):1:wingcc:9:wingcc\n"; 00074 00075 // Struct to hold device-specific info. 00076 00077 typedef struct 00078 { 00079 PLFLT scale; // scaling factor to "blow up" to the "virtual" page in removing hidden lines 00080 PLINT width; // Window width (which can change) 00081 PLINT height; // Window Height 00082 00083 PLFLT PRNT_scale; 00084 PLINT PRNT_width; 00085 PLINT PRNT_height; 00086 00087 PLGraphicsIn gin; 00088 00089 char FT_smooth_text; 00090 // 00091 // WIN32 API variables 00092 // 00093 00094 COLORREF colour; // Current Colour 00095 COLORREF oldcolour; // Used for high-speed background erasing 00096 MSG msg; // A Win32 message structure. 00097 WNDCLASSEX wndclass; // An extended window class structure. 00098 HWND hwnd; // Handle for the main window. 00099 HPEN pen; // Windows pen used for drawing 00100 HDC hdc; // Driver Context 00101 HDC hdc2; // Driver Context II - used for Blitting 00102 HDC SCRN_hdc; // The screen's context 00103 HDC PRNT_hdc; // used for printing 00104 PAINTSTRUCT ps; // used to paint the client area of a window owned by that application 00105 RECT rect; // defines the coordinates of the upper-left and lower-right corners of a rectangle 00106 RECT oldrect; // used for re-sizing comparisons 00107 RECT paintrect; // used for painting etc... 00108 HBRUSH fillbrush; // brush used for fills 00109 HCURSOR cursor; // Current windows cursor for this window 00110 HBITMAP bitmap; // Bitmap of current display; used for fast redraws via blitting 00111 HGDIOBJ oldobject; // Used for tracking objects probably not really needed but 00112 HMENU PopupMenu; 00113 00114 PLINT draw_mode; 00115 char truecolour; // Flag to indicate 24 bit mode 00116 char waiting; // Flag to indicate drawing is done, and it is waiting; 00117 // we only do a windows redraw if plplot is plotting 00118 char enterresize; // Used to keep track of reszing messages from windows 00119 char already_erased; // Used to track first and only first backgroudn erases 00120 00121 struct wingcc_Dev *push; // A copy of the entire structure used when printing 00122 // We push and pop it off a virtual stack 00123 } wingcc_Dev; 00124 00125 00126 void plD_dispatch_init_wingcc( PLDispatchTable *pdt ); 00127 00128 void plD_init_wingcc( PLStream * ); 00129 void plD_line_wingcc( PLStream *, short, short, short, short ); 00130 void plD_polyline_wingcc( PLStream *, short *, short *, PLINT ); 00131 void plD_eop_wingcc( PLStream * ); 00132 void plD_bop_wingcc( PLStream * ); 00133 void plD_tidy_wingcc( PLStream * ); 00134 void plD_state_wingcc( PLStream *, PLINT ); 00135 void plD_esc_wingcc( PLStream *, PLINT, void * ); 00136 00137 #ifdef PL_HAVE_FREETYPE 00138 00139 static void plD_pixel_wingcc( PLStream *pls, short x, short y ); 00140 static void plD_pixelV_wingcc( PLStream *pls, short x, short y ); 00141 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y ); 00142 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour ); 00143 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour ); 00144 static void init_freetype_lv1( PLStream *pls ); 00145 static void init_freetype_lv2( PLStream *pls ); 00146 00147 #endif 00148 00149 00150 //-------------------------------------------------------------------------- 00151 // Local Function definitions and function-like defines 00152 //-------------------------------------------------------------------------- 00153 00154 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size ); 00155 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size ); 00156 static void Resize( PLStream *pls ); 00157 static void plD_fill_polygon_wingcc( PLStream *pls ); 00158 static void CopySCRtoBMP( PLStream *pls ); 00159 static void PrintPage( PLStream *pls ); 00160 static void UpdatePageMetrics( PLStream *pls, char flag ); 00161 00162 #define SetRegStringValue( a, b, c ) SetRegValue( a, b, c, REG_SZ, strlen( c ) + 1 ) 00163 #define SetRegBinaryValue( a, b, c, d ) SetRegValue( a, b, (char *) c, REG_BINARY, d ) 00164 #define SetRegIntValue( a, b, c ) SetRegValue( a, b, (char *) c, REG_DWORD, 4 ) 00165 #define GetRegStringValue( a, b, c, d ) GetRegValue( a, b, c, d ) 00166 #define GetRegIntValue( a, b, c ) GetRegValue( a, b, (char *) c, 4 ) 00167 #define GetRegBinaryValue( a, b, c, d ) GetRegValue( a, b, (char *) c, d ) 00168 00169 //-------------------------------------------------------------------------- 00170 // Some debugging macros 00171 //-------------------------------------------------------------------------- 00172 00173 #if defined ( _MSC_VER ) 00174 #define Debug( a ) do { if ( pls->debug ) { fprintf( stderr, ( a ) ); } } while ( 0 ) 00175 #define Debug2( a, b ) do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ) ); } } while ( 0 ) 00176 #define Debug3( a, b, c ) do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ), ( c ) ); } } while ( 0 ) 00177 #elif defined ( __BORLANDC__ ) 00178 #define Debug if ( pls->debug ) printf 00179 #define Debug2 if ( pls->debug ) printf 00180 #define Debug3 if ( pls->debug ) printf 00181 #else 00182 #define Verbose( ... ) do { if ( pls->verbose ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 ) 00183 #define Debug( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 ) 00184 #define Debug2( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 ) 00185 #define Debug3( ... ) do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 ) 00186 #endif 00187 00188 #define ReportWinError() do { \ 00189 LPVOID lpMsgBuf; \ 00190 FormatMessage( \ 00191 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \ 00192 NULL, GetLastError(), \ 00193 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL ); \ 00194 MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK | MB_ICONINFORMATION ); \ 00195 LocalFree( lpMsgBuf ); } while ( 0 ) 00196 00197 #define CrossHairCursor() do { \ 00198 dev->cursor = LoadCursor( NULL, IDC_CROSS ); \ 00199 SetClassLong( dev->hwnd, GCL_HCURSOR, (long) dev->cursor ); \ 00200 SetCursor( dev->cursor ); } while ( 0 ) 00201 00202 #define NormalCursor() do { \ 00203 dev->cursor = LoadCursor( NULL, IDC_ARROW ); \ 00204 SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \ 00205 SetCursor( dev->cursor ); } while ( 0 ) 00206 00207 #define BusyCursor() do { \ 00208 dev->cursor = LoadCursor( NULL, IDC_WAIT ); \ 00209 SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \ 00210 SetCursor( dev->cursor ); } while ( 0 ) 00211 00212 #define PopupPrint 0x08A1 00213 #define PopupNextPage 0x08A2 00214 #define PopupQuit 0x08A3 00215 00216 00217 void plD_dispatch_init_wingcc( PLDispatchTable *pdt ) 00218 { 00219 #ifndef ENABLE_DYNDRIVERS 00220 pdt->pl_MenuStr = "Win32 GCC device"; 00221 pdt->pl_DevName = "wingcc"; 00222 #endif 00223 pdt->pl_type = plDevType_Interactive; 00224 pdt->pl_seq = 9; 00225 pdt->pl_init = (plD_init_fp) plD_init_wingcc; 00226 pdt->pl_line = (plD_line_fp) plD_line_wingcc; 00227 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wingcc; 00228 pdt->pl_eop = (plD_eop_fp) plD_eop_wingcc; 00229 pdt->pl_bop = (plD_bop_fp) plD_bop_wingcc; 00230 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wingcc; 00231 pdt->pl_state = (plD_state_fp) plD_state_wingcc; 00232 pdt->pl_esc = (plD_esc_fp) plD_esc_wingcc; 00233 } 00234 00235 static TCHAR* szWndClass = _T( "PlplotWin" ); 00236 00237 00238 //-------------------------------------------------------------------------- 00239 // This is the window function for the plot window. Whenever a message is 00240 // dispatched using DispatchMessage (or sent with SendMessage) this function 00241 // gets called with the contents of the message. 00242 //-------------------------------------------------------------------------- 00243 00244 LRESULT CALLBACK PlplotWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 00245 { 00246 PLStream *pls = NULL; 00247 wingcc_Dev *dev = NULL; 00248 00249 // 00250 // The window carries a 32bit user defined pointer which points to the 00251 // plplot stream (pls). This is used for tracking the window. 00252 // Unfortunately, this is "attached" to the window AFTER it is created 00253 // so we can not initialise PLStream or wingcc_Dev "blindly" because 00254 // they may not yet have been initialised. 00255 // WM_CREATE is called before we get to initialise those variables, so 00256 // we wont try to set them. 00257 // 00258 00259 if ( nMsg == WM_CREATE ) 00260 { 00261 return ( 0 ); 00262 } 00263 else 00264 { 00265 #ifndef _WIN64 00266 #undef GetWindowLongPtr 00267 #define GetWindowLongPtr GetWindowLong 00268 #endif 00269 pls = (PLStream *) GetWindowLongPtr( hwnd, GWL_USERDATA ); // Try to get the address to pls for this window 00270 if ( pls ) // If we got it, then we will initialise this windows plplot private data area 00271 { 00272 dev = (wingcc_Dev *) pls->dev; 00273 } 00274 } 00275 00276 // 00277 // Process the windows messages 00278 // 00279 // Everything except WM_CREATE is done here and it is generally hoped that 00280 // pls and dev are defined already by this stage. 00281 // That will be true MOST of the time. Some times WM_PAINT will be called 00282 // before we get to initialise the user data area of the window with the 00283 // pointer to the windows plplot stream 00284 // 00285 00286 switch ( nMsg ) 00287 { 00288 case WM_DESTROY: 00289 if ( dev ) 00290 Debug( "WM_DESTROY\t" ); 00291 PostQuitMessage( 0 ); 00292 return ( 0 ); 00293 break; 00294 00295 case WM_PAINT: 00296 if ( dev ) 00297 { 00298 Debug( "WM_PAINT\t" ); 00299 if ( GetUpdateRect( dev->hwnd, &dev->paintrect, TRUE ) ) 00300 { 00301 BusyCursor(); 00302 BeginPaint( dev->hwnd, &dev->ps ); 00303 00304 if ( ( dev->waiting == 1 ) && ( dev->already_erased == 1 ) ) 00305 { 00306 Debug( "Remaking\t" ); 00307 00308 if ( dev->ps.fErase ) 00309 { 00310 dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) ); 00311 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 ); 00312 SetBkColor( dev->hdc, dev->oldcolour ); 00313 } 00314 00315 plRemakePlot( pls ); 00316 CopySCRtoBMP( pls ); 00317 dev->already_erased++; 00318 } 00319 else if ( ( dev->waiting == 1 ) && ( dev->already_erased == 2 ) ) 00320 { 00321 dev->oldobject = SelectObject( dev->hdc2, dev->bitmap ); 00322 BitBlt( dev->hdc, dev->paintrect.left, dev->paintrect.top, 00323 dev->paintrect.right, dev->paintrect.bottom, 00324 dev->hdc2, dev->paintrect.left, dev->paintrect.top, SRCCOPY ); 00325 SelectObject( dev->hdc2, dev->oldobject ); 00326 } 00327 00328 EndPaint( dev->hwnd, &dev->ps ); 00329 NormalCursor(); 00330 return ( 0 ); 00331 } 00332 } 00333 return ( 1 ); 00334 break; 00335 00336 case WM_SIZE: 00337 if ( dev ) 00338 { 00339 Debug( "WM_SIZE\t" ); 00340 00341 if ( dev->enterresize == 0 ) 00342 Resize( pls ); 00343 } 00344 return ( 0 ); 00345 break; 00346 00347 case WM_ENTERSIZEMOVE: 00348 if ( dev ) 00349 { 00350 Debug( "WM_ENTERSIZEMOVE\t" ); 00351 dev->enterresize = 1; 00352 } 00353 return ( 0 ); 00354 break; 00355 00356 00357 case WM_EXITSIZEMOVE: 00358 if ( dev ) 00359 { 00360 Debug( "WM_EXITSIZEMOVE\t" ); 00361 Resize( pls ); 00362 dev->enterresize = 0; // Reset the variables that track sizing ops 00363 } 00364 return ( 0 ); 00365 break; 00366 00367 case WM_ERASEBKGND: 00368 00369 if ( dev ) 00370 { 00371 if ( dev->already_erased == 0 ) 00372 { 00373 Debug( "WM_ERASEBKGND\t" ); 00374 00375 // 00376 // This is a new "High Speed" way of filling in the background. 00377 // supposidely this executes faster than creating a brush and 00378 // filling a rectangle - go figure ? 00379 // 00380 00381 dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) ); 00382 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 ); 00383 SetBkColor( dev->hdc, dev->oldcolour ); 00384 00385 dev->already_erased = 1; 00386 return ( 1 ); 00387 } 00388 } 00389 return ( 0 ); 00390 break; 00391 00392 case WM_COMMAND: 00393 if ( dev ) 00394 Debug( "WM_COMMAND\t" ); 00395 return ( 0 ); 00396 break; 00397 } 00398 00399 // If we don't handle a message completely we hand it to the system 00400 // provided default window function. 00401 return DefWindowProc( hwnd, nMsg, wParam, lParam ); 00402 } 00403 00404 00405 //-------------------------------------------------------------------------- 00406 // plD_init_wingcc() 00407 // 00408 // Initialize device (terminal). 00409 //-------------------------------------------------------------------------- 00410 00411 void 00412 plD_init_wingcc( PLStream *pls ) 00413 { 00414 wingcc_Dev *dev; 00415 00416 #ifdef PL_HAVE_FREETYPE 00417 static int freetype = 0; 00418 static int smooth_text = 0; 00419 static int save_reg = 0; 00420 FT_Data *FT; 00421 00422 // 00423 // Variables used for reading the registary keys 00424 // might eventually add a user defined pallette here, but for now it just does freetype 00425 // 00426 TCHAR key_name[] = _T( "Software\\PLplot\\wingcc" ); 00427 TCHAR Keyword_text[] = _T( "freetype" ); 00428 TCHAR Keyword_smooth[] = _T( "smooth" ); 00429 #endif 00430 00431 DrvOpt wingcc_options[] = { 00432 #ifdef PL_HAVE_FREETYPE 00433 { "text", DRV_INT, &freetype, "Use driver text (FreeType)" }, 00434 { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" }, 00435 { "save", DRV_INT, &save_reg, "Save defaults to registary" }, 00436 00437 #endif 00438 { NULL, DRV_INT, NULL, NULL } 00439 }; 00440 00441 // 00442 // Variable for storing the program name 00443 // 00444 TCHAR *program; 00445 int programlength; 00446 00447 // Allocate and initialize device-specific data 00448 00449 if ( pls->dev != NULL ) 00450 free( (void *) pls->dev ); 00451 00452 pls->dev = calloc( 1, (size_t) sizeof ( wingcc_Dev ) ); 00453 if ( pls->dev == NULL ) 00454 plexit( "plD_init_wingcc_Dev: Out of memory." ); 00455 00456 dev = (wingcc_Dev *) pls->dev; 00457 00458 pls->icol0 = 1; // Set a fall back pen colour in case user doesn't 00459 00460 pls->termin = 1; // interactive device 00461 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) 00462 pls->dev_fill0 = 1; // driver can do solid area fills 00463 pls->dev_xor = 1; // driver supports xor mode 00464 pls->dev_clear = 0; // driver does not support clear - what is the proper API? 00465 pls->dev_dash = 0; // driver can not do dashed lines (yet) 00466 pls->plbuf_write = 1; // driver uses the buffer for redraws 00467 00468 if ( !pls->colorset ) 00469 pls->color = 1; 00470 00471 00472 #ifdef PL_HAVE_FREETYPE 00473 00474 // 00475 // Read registry to see if the user has set up default values 00476 // for text and smoothing. These will be overriden by anything that 00477 // might be given on the command line, so we will load the 00478 // values right into the same memory slots we pass to plParseDrvOpts 00479 // 00480 00481 GetRegIntValue( key_name, Keyword_text, &freetype ); 00482 GetRegIntValue( key_name, Keyword_smooth, &smooth_text ); 00483 00484 #endif 00485 00486 // Check for and set up driver options 00487 00488 plParseDrvOpts( wingcc_options ); 00489 00490 #ifdef PL_HAVE_FREETYPE 00491 00492 // 00493 // We will now save the settings to the registary if the user wants 00494 // 00495 00496 if ( save_reg == 1 ) 00497 { 00498 SetRegIntValue( key_name, Keyword_text, &freetype ); 00499 SetRegIntValue( key_name, Keyword_smooth, &smooth_text ); 00500 } 00501 00502 #endif 00503 00504 // Set up device parameters 00505 00506 if ( pls->xlength <= 0 || pls->ylength <= 0 ) 00507 { 00508 // use default width, height of 800x600 if not specifed by -geometry option 00509 // or plspage 00510 plspage( 0., 0., 800, 600, 0, 0 ); 00511 } 00512 00513 dev->width = pls->xlength - 1; // should I use -1 or not??? 00514 dev->height = pls->ylength - 1; 00515 00516 // 00517 // Begin initialising the window 00518 // 00519 00520 // Initialize the entire structure to zero. 00521 memset( &dev->wndclass, 0, sizeof ( WNDCLASSEX ) ); 00522 00523 // This class is called WinTestWin 00524 dev->wndclass.lpszClassName = szWndClass; 00525 00526 // cbSize gives the size of the structure for extensibility. 00527 dev->wndclass.cbSize = sizeof ( WNDCLASSEX ); 00528 00529 // All windows of this class redraw when resized. 00530 dev->wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC | CS_PARENTDC; 00531 00532 // All windows of this class use the WndProc window function. 00533 dev->wndclass.lpfnWndProc = PlplotWndProc; 00534 00535 // This class is used with the current program instance. 00536 00537 dev->wndclass.hInstance = GetModuleHandle( NULL ); 00538 00539 // Use standard application icon and arrow cursor provided by the OS 00540 dev->wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); 00541 dev->wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); 00542 dev->wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); 00543 // Color the background white 00544 dev->wndclass.hbrBackground = NULL; 00545 00546 dev->wndclass.cbWndExtra = sizeof ( pls ); 00547 00548 00549 // 00550 // Now register the window class for use. 00551 // 00552 00553 RegisterClassEx( &dev->wndclass ); 00554 00555 // 00556 //convert the program name to wide char if needed 00557 // 00558 00559 #ifdef UNICODE 00560 printf( pls->program ); 00561 programlength = strlen( pls->program ) + 1; 00562 program = malloc( programlength * sizeof ( TCHAR ) ); 00563 MultiByteToWideChar( CP_UTF8, 0, pls->program, programlength, program, programlength ); 00564 #else 00565 program = pls->program; 00566 #endif 00567 // 00568 // Create our main window using that window class. 00569 // 00570 dev->hwnd = CreateWindowEx( WS_EX_WINDOWEDGE + WS_EX_LEFT, 00571 szWndClass, // Class name 00572 program, // Caption 00573 WS_OVERLAPPEDWINDOW, // Style 00574 pls->xoffset, // Initial x (use default) 00575 pls->yoffset, // Initial y (use default) 00576 pls->xlength, // Initial x size (use default) 00577 pls->ylength, // Initial y size (use default) 00578 NULL, // No parent window 00579 NULL, // No menu 00580 dev->wndclass.hInstance, // This program instance 00581 NULL // Creation parameters 00582 ); 00583 00584 #ifdef UNICODE 00585 free( program ); 00586 #endif 00587 00588 // 00589 // Attach a pointer to the stream to the window's user area 00590 // this pointer will be used by the windows call back for 00591 // process this window 00592 // 00593 00594 #ifdef _WIN64 00595 SetWindowLongPtr( dev->hwnd, GWL_USERDATA, (LONG_PTR) pls ); 00596 #else 00597 SetWindowLong( dev->hwnd, GWL_USERDATA, (LONG) pls ); 00598 #endif 00599 00600 dev->SCRN_hdc = dev->hdc = GetDC( dev->hwnd ); 00601 00602 // 00603 // Setup the popup menu 00604 // 00605 00606 dev->PopupMenu = CreatePopupMenu(); 00607 AppendMenu( dev->PopupMenu, MF_STRING, PopupPrint, _T( "Print" ) ); 00608 AppendMenu( dev->PopupMenu, MF_STRING, PopupNextPage, _T( "Next Page" ) ); 00609 AppendMenu( dev->PopupMenu, MF_STRING, PopupQuit, _T( "Quit" ) ); 00610 00611 #ifdef PL_HAVE_FREETYPE 00612 00613 if ( freetype ) 00614 { 00615 pls->dev_text = 1; // want to draw text 00616 pls->dev_unicode = 1; // want unicode 00617 init_freetype_lv1( pls ); 00618 FT = (FT_Data *) pls->FT; 00619 FT->want_smooth_text = smooth_text; 00620 } 00621 00622 #endif 00623 00624 00625 00626 plD_state_wingcc( pls, PLSTATE_COLOR0 ); 00627 // 00628 // Display the window which we just created (using the nShow 00629 // passed by the OS, which allows for start minimized and that 00630 // sort of thing). 00631 // 00632 ShowWindow( dev->hwnd, SW_SHOWDEFAULT ); 00633 SetForegroundWindow( dev->hwnd ); 00634 00635 // 00636 // Set up the DPI etc... 00637 // 00638 00639 00640 if ( pls->xdpi <= 0 ) // Get DPI from windows 00641 { 00642 plspage( GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4, 00643 GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4, 0, 0, 0, 0 ); 00644 } 00645 else 00646 { 00647 pls->ydpi = pls->xdpi; // Set X and Y dpi's to the same value 00648 } 00649 00650 00651 // 00652 // Now we have to find out, from windows, just how big our drawing area is 00653 // when we specified the page size earlier on, that includes the borders, 00654 // title bar etc... so now that windows has done all its initialisations, 00655 // we will ask how big the drawing area is, and tell plplot 00656 // 00657 00658 GetClientRect( dev->hwnd, &dev->rect ); 00659 dev->width = dev->rect.right; 00660 dev->height = dev->rect.bottom; 00661 00662 if ( dev->width > dev->height ) // Work out the scaling factor for the 00663 { // "virtual" (oversized) page 00664 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width; 00665 } 00666 else 00667 { 00668 dev->scale = (PLFLT) PIXELS_Y / dev->height; 00669 } 00670 00671 Debug2( "Scale = %f (FLT)\n", dev->scale ); 00672 00673 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 ); 00674 plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) ); 00675 00676 // Set fill rule. 00677 if ( pls->dev_eofill ) 00678 SetPolyFillMode( dev->hdc, ALTERNATE ); 00679 else 00680 SetPolyFillMode( dev->hdc, WINDING ); 00681 00682 #ifdef PL_HAVE_FREETYPE 00683 if ( pls->dev_text ) 00684 { 00685 init_freetype_lv2( pls ); 00686 } 00687 #endif 00688 } 00689 00690 //-------------------------------------------------------------------------- 00691 // plD_line_wingcc() 00692 // 00693 // Draw a line in the current color from (x1,y1) to (x2,y2). 00694 //-------------------------------------------------------------------------- 00695 00696 void 00697 plD_line_wingcc( PLStream *pls, short x1a, short y1a, short x2a, short y2a ) 00698 { 00699 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00700 POINT points[2]; 00701 00702 00703 points[0].x = (LONG) ( x1a / dev->scale ); 00704 points[1].x = (LONG) ( x2a / dev->scale ); 00705 points[0].y = (LONG) ( dev->height - ( y1a / dev->scale ) ); 00706 points[1].y = (LONG) ( dev->height - ( y2a / dev->scale ) ); 00707 00708 dev->oldobject = SelectObject( dev->hdc, dev->pen ); 00709 00710 if ( points[0].x != points[1].x || points[0].y != points[1].y ) 00711 { 00712 Polyline( dev->hdc, points, 2 ); 00713 } 00714 else 00715 { 00716 SetPixel( dev->hdc, points[0].x, points[0].y, dev->colour ); 00717 } 00718 SelectObject( dev->hdc, dev->oldobject ); 00719 } 00720 00721 00722 //-------------------------------------------------------------------------- 00723 // plD_polyline_wingcc() 00724 // 00725 // Draw a polyline in the current color. 00726 //-------------------------------------------------------------------------- 00727 00728 void 00729 plD_polyline_wingcc( PLStream *pls, short *xa, short *ya, PLINT npts ) 00730 { 00731 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00732 int i; 00733 POINT *points = NULL; 00734 00735 if ( npts > 0 ) 00736 { 00737 points = GlobalAlloc( GMEM_ZEROINIT | GMEM_FIXED, (size_t) npts * sizeof ( POINT ) ); 00738 if ( points != NULL ) 00739 { 00740 for ( i = 0; i < npts; i++ ) 00741 { 00742 points[i].x = (LONG) ( xa[i] / dev->scale ); 00743 points[i].y = (LONG) ( dev->height - ( ya[i] / dev->scale ) ); 00744 } 00745 dev->oldobject = SelectObject( dev->hdc, dev->pen ); 00746 Polyline( dev->hdc, points, npts ); 00747 SelectObject( dev->hdc, dev->oldobject ); 00748 GlobalFree( points ); 00749 } 00750 else 00751 { 00752 plexit( "Could not allocate memory to \"plD_polyline_wingcc\"\n" ); 00753 } 00754 } 00755 } 00756 00757 //-------------------------------------------------------------------------- 00758 // plD_fill_polygon_wingcc() 00759 // 00760 // Fill polygon described in points pls->dev_x[] and pls->dev_y[]. 00761 //-------------------------------------------------------------------------- 00762 00763 static void 00764 plD_fill_polygon_wingcc( PLStream *pls ) 00765 { 00766 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00767 int i; 00768 POINT *points = NULL; 00769 HPEN hpen, hpenOld; 00770 00771 if ( pls->dev_npts > 0 ) 00772 { 00773 points = GlobalAlloc( GMEM_ZEROINIT, (size_t) pls->dev_npts * sizeof ( POINT ) ); 00774 00775 if ( points == NULL ) 00776 plexit( "Could not allocate memory to \"plD_fill_polygon_wingcc\"\n" ); 00777 00778 for ( i = 0; i < pls->dev_npts; i++ ) 00779 { 00780 points[i].x = (PLINT) ( pls->dev_x[i] / dev->scale ); 00781 points[i].y = (PLINT) ( dev->height - ( pls->dev_y[i] / dev->scale ) ); 00782 } 00783 00784 dev->fillbrush = CreateSolidBrush( dev->colour ); 00785 hpen = CreatePen( PS_SOLID, 1, dev->colour ); 00786 dev->oldobject = SelectObject( dev->hdc, dev->fillbrush ); 00787 hpenOld = SelectObject( dev->hdc, hpen ); 00788 Polygon( dev->hdc, points, pls->dev_npts ); 00789 SelectObject( dev->hdc, dev->oldobject ); 00790 DeleteObject( dev->fillbrush ); 00791 SelectObject( dev->hdc, hpenOld ); 00792 DeleteObject( hpen ); 00793 GlobalFree( points ); 00794 } 00795 } 00796 00797 //-------------------------------------------------------------------------- 00798 // static void CopySCRtoBMP(PLStream *pls) 00799 // Function copies the screen contents into a bitmap which is 00800 // later used for fast redraws of the screen (when it gets corrupted) 00801 // rather than remaking the plot from the plot buffer. 00802 //-------------------------------------------------------------------------- 00803 00804 static void CopySCRtoBMP( PLStream *pls ) 00805 { 00806 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00807 00808 // 00809 // Clean up the old bitmap and DC 00810 // 00811 00812 if ( dev->hdc2 != NULL ) 00813 DeleteDC( dev->hdc2 ); 00814 if ( dev->bitmap != NULL ) 00815 DeleteObject( dev->bitmap ); 00816 00817 dev->hdc2 = CreateCompatibleDC( dev->hdc ); 00818 GetClientRect( dev->hwnd, &dev->rect ); 00819 dev->bitmap = CreateCompatibleBitmap( dev->hdc, dev->rect.right, dev->rect.bottom ); 00820 dev->oldobject = SelectObject( dev->hdc2, dev->bitmap ); 00821 BitBlt( dev->hdc2, 0, 0, dev->rect.right, dev->rect.bottom, dev->hdc, 0, 0, SRCCOPY ); 00822 SelectObject( dev->hdc2, dev->oldobject ); 00823 } 00824 00825 00826 00827 void 00828 plD_eop_wingcc( PLStream *pls ) 00829 { 00830 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00831 00832 Debug( "End of the page\n" ); 00833 CopySCRtoBMP( pls ); 00834 dev->already_erased = 2; 00835 00836 NormalCursor(); 00837 00838 if ( !pls->nopause ) 00839 { 00840 dev->waiting = 1; 00841 while ( GetMessage( &dev->msg, NULL, 0, 0 ) ) 00842 { 00843 TranslateMessage( &dev->msg ); 00844 switch ( (int) dev->msg.message ) 00845 { 00846 case WM_CONTEXTMENU: 00847 case WM_RBUTTONDOWN: 00848 TrackPopupMenu( dev->PopupMenu, TPM_CENTERALIGN | TPM_RIGHTBUTTON, LOWORD( dev->msg.lParam ), 00849 HIWORD( dev->msg.lParam ), 0, dev->hwnd, NULL ); 00850 break; 00851 00852 case WM_CHAR: 00853 if ( ( (TCHAR) ( dev->msg.wParam ) == 32 ) || 00854 ( (TCHAR) ( dev->msg.wParam ) == 13 ) ) 00855 { 00856 dev->waiting = 0; 00857 } 00858 else if ( ( (TCHAR) ( dev->msg.wParam ) == 27 ) || 00859 ( (TCHAR) ( dev->msg.wParam ) == 'q' ) || 00860 ( (TCHAR) ( dev->msg.wParam ) == 'Q' ) ) 00861 { 00862 dev->waiting = 0; 00863 PostQuitMessage( 0 ); 00864 } 00865 break; 00866 00867 case WM_LBUTTONDBLCLK: 00868 Debug( "WM_LBUTTONDBLCLK\t" ); 00869 dev->waiting = 0; 00870 break; 00871 00872 case WM_COMMAND: 00873 switch ( LOWORD( dev->msg.wParam ) ) 00874 { 00875 case PopupPrint: 00876 Debug( "PopupPrint" ); 00877 PrintPage( pls ); 00878 break; 00879 case PopupNextPage: 00880 Debug( "PopupNextPage" ); 00881 dev->waiting = 0; 00882 break; 00883 case PopupQuit: 00884 Debug( "PopupQuit" ); 00885 dev->waiting = 0; 00886 PostQuitMessage( 0 ); 00887 break; 00888 } 00889 break; 00890 00891 default: 00892 DispatchMessage( &dev->msg ); 00893 break; 00894 } 00895 if ( dev->waiting == 0 ) 00896 break; 00897 } 00898 } 00899 } 00900 00901 //-------------------------------------------------------------------------- 00902 // Beginning of the new page 00903 //-------------------------------------------------------------------------- 00904 void 00905 plD_bop_wingcc( PLStream *pls ) 00906 { 00907 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00908 #ifdef PL_HAVE_FREETYPE 00909 FT_Data *FT = (FT_Data *) pls->FT; 00910 #endif 00911 Debug( "Start of Page\t" ); 00912 00913 // 00914 // Turn the cursor to a busy sign, clear the page by "invalidating" it 00915 // then reset the colours and pen width 00916 // 00917 00918 BusyCursor(); 00919 dev->already_erased = 0; 00920 RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW ); 00921 00922 plD_state_wingcc( pls, PLSTATE_COLOR0 ); 00923 } 00924 00925 void 00926 plD_tidy_wingcc( PLStream *pls ) 00927 { 00928 wingcc_Dev *dev = NULL; 00929 00930 #ifdef PL_HAVE_FREETYPE 00931 if ( pls->dev_text ) 00932 { 00933 FT_Data *FT = (FT_Data *) pls->FT; 00934 plscmap0n( FT->ncol0_org ); 00935 plD_FreeType_Destroy( pls ); 00936 } 00937 #endif 00938 Debug( "plD_tidy_wingcc" ); 00939 00940 if ( pls->dev != NULL ) 00941 { 00942 dev = (wingcc_Dev *) pls->dev; 00943 00944 DeleteMenu( dev->PopupMenu, PopupPrint, 0 ); 00945 DeleteMenu( dev->PopupMenu, PopupNextPage, 0 ); 00946 DeleteMenu( dev->PopupMenu, PopupQuit, 0 ); 00947 DestroyMenu( dev->PopupMenu ); 00948 00949 if ( dev->hdc2 != NULL ) 00950 DeleteDC( dev->hdc2 ); 00951 if ( dev->hdc != NULL ) 00952 ReleaseDC( dev->hwnd, dev->hdc ); 00953 if ( dev->bitmap != NULL ) 00954 DeleteObject( dev->bitmap ); 00955 00956 free_mem( pls->dev ); 00957 } 00958 } 00959 00960 00961 00962 00963 //-------------------------------------------------------------------------- 00964 // plD_state_png() 00965 // 00966 // Handle change in PLStream state (color, pen width, fill attribute, etc). 00967 //-------------------------------------------------------------------------- 00968 00969 void 00970 plD_state_wingcc( PLStream *pls, PLINT op ) 00971 { 00972 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 00973 00974 switch ( op ) 00975 { 00976 case PLSTATE_COLOR0: 00977 case PLSTATE_COLOR1: 00978 dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ); 00979 break; 00980 00981 case PLSTATE_CMAP0: 00982 case PLSTATE_CMAP1: 00983 dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ); 00984 break; 00985 } 00986 00987 if ( dev->pen != NULL ) 00988 DeleteObject( dev->pen ); 00989 dev->pen = CreatePen( PS_SOLID, pls->width, dev->colour ); 00990 } 00991 00992 //-------------------------------------------------------------------------- 00993 // GetCursorCmd() 00994 // 00995 // Handle events connected to selecting points (modelled after xwin) 00996 //-------------------------------------------------------------------------- 00997 00998 static void 00999 GetCursorCmd( PLStream *pls, PLGraphicsIn *gin ) 01000 { 01001 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01002 01003 HCURSOR crosshair; 01004 HCURSOR previous; 01005 01006 plGinInit( gin ); 01007 01008 crosshair = LoadCursor( GetModuleHandle( NULL ), IDC_CROSS ); 01009 previous = SetCursor( crosshair ); 01010 01011 while ( gin->pX < 0 ) 01012 { 01013 GetMessage( &dev->msg, NULL, 0, 0 ); 01014 TranslateMessage( &dev->msg ); 01015 switch ( (int) dev->msg.message ) 01016 { 01017 case WM_LBUTTONDOWN: 01018 if ( dev->msg.wParam & MK_LBUTTON ) 01019 { 01020 gin->pX = dev->msg.pt.x; 01021 gin->pY = dev->msg.pt.y; 01022 gin->dX = (PLFLT) gin->pX / ( dev->width - 1 ); 01023 gin->dY = 1.0 - (PLFLT) gin->pY / ( dev->height - 1 ); 01024 01025 gin->button = 1; // AM: there is no macro to indicate the pressed button! 01026 gin->state = 0; // AM: is there an equivalent under Windows? 01027 gin->keysym = 0x20; 01028 } 01029 break; 01030 case WM_CHAR: 01031 gin->pX = dev->msg.pt.x; 01032 gin->pY = dev->msg.pt.y; 01033 gin->dX = (PLFLT) gin->pX / ( dev->width - 1 ); 01034 gin->dY = 1.0 - (PLFLT) gin->pY / ( dev->height - 1 ); 01035 01036 gin->button = 0; 01037 gin->state = 0; 01038 gin->keysym = dev->msg.wParam; 01039 01040 break; 01041 } 01042 } 01043 01044 // Restore the previous cursor 01045 SetCursor( previous ); 01046 01047 // if ( GetCursorPos(&p) ) 01048 // { 01049 // if ( ScreenToClient( dev->hwnd, &p ) ) 01050 // { 01051 // // Fill the fields, but actually we need to run the event loop 01052 // // We need to call GetMessage() in a loop. Unclear as yet to the 01053 // // actual interface: key/button presses? 01054 // } 01055 // } 01056 } 01057 01058 //-------------------------------------------------------------------------- 01059 // plD_esc_wingcc() 01060 // 01061 // Handle PLplot escapes 01062 //-------------------------------------------------------------------------- 01063 01064 void 01065 plD_esc_wingcc( PLStream *pls, PLINT op, void *ptr ) 01066 { 01067 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01068 PLGraphicsIn *gin = &( dev->gin ); 01069 01070 01071 switch ( op ) 01072 { 01073 case PLESC_GETC: 01074 GetCursorCmd( pls, (PLGraphicsIn *) ptr ); 01075 break; 01076 01077 case PLESC_FILL: 01078 plD_fill_polygon_wingcc( pls ); 01079 break; 01080 01081 case PLESC_DOUBLEBUFFERING: 01082 break; 01083 01084 case PLESC_XORMOD: 01085 if ( *(PLINT *) ( ptr ) == 0 ) 01086 SetROP2( dev->hdc, R2_COPYPEN ); 01087 else 01088 SetROP2( dev->hdc, R2_XORPEN ); 01089 break; 01090 01091 #ifdef PL_HAVE_FREETYPE 01092 case PLESC_HAS_TEXT: 01093 plD_render_freetype_text( pls, (EscText *) ptr ); 01094 break; 01095 01096 // case PLESC_LIKES_UNICODE: 01097 // plD_render_freetype_sym(pls, (EscText *)ptr); 01098 // break; 01099 01100 #endif 01101 } 01102 } 01103 01104 //-------------------------------------------------------------------------- 01105 // static void Resize( PLStream *pls ) 01106 // 01107 // This function calculates how to resize a window after a message has been 01108 // received from windows telling us the window has been changed. 01109 // It tries to recalculate the scale of the window so everything works out 01110 // just right. 01111 // The window is only resized if plplot has finished all of its plotting. 01112 // That means that if you resize while a picture is being plotted, 01113 // unpredictable results may result. The reason I do this is because the 01114 // resize function calls redraw window, which replays the whole plot. 01115 //-------------------------------------------------------------------------- 01116 01117 static void Resize( PLStream *pls ) 01118 { 01119 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01120 #ifdef PL_HAVE_FREETYPE 01121 FT_Data *FT = (FT_Data *) pls->FT; 01122 #endif 01123 Debug( "Resizing" ); 01124 01125 if ( dev->waiting == 1 ) // Only resize the window IF plplot has finished with it 01126 { 01127 memcpy( &dev->oldrect, &dev->rect, sizeof ( RECT ) ); 01128 GetClientRect( dev->hwnd, &dev->rect ); 01129 Debug3( "[%d %d]", dev->rect.right, dev->rect.bottom ); 01130 01131 if ( ( dev->rect.right > 0 ) && ( dev->rect.bottom > 0 ) ) // Check to make sure it isn't just minimised (i.e. zero size) 01132 { 01133 if ( memcmp( &dev->rect, &dev->oldrect, sizeof ( RECT ) ) != 0 ) // See if the window's changed size or not 01134 { 01135 dev->already_erased = 0; 01136 dev->width = dev->rect.right; 01137 dev->height = dev->rect.bottom; 01138 if ( dev->width > dev->height ) // Work out the scaling factor for the 01139 { // "virtual" (oversized) page 01140 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width; 01141 } 01142 else 01143 { 01144 dev->scale = (PLFLT) PIXELS_Y / dev->height; 01145 } 01146 01147 #ifdef PL_HAVE_FREETYPE 01148 if ( FT ) 01149 { 01150 FT->scale = dev->scale; 01151 FT->ymax = dev->height; 01152 } 01153 #endif 01154 } 01155 RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW ); 01156 } 01157 else 01158 { 01159 memcpy( &dev->rect, &dev->oldrect, sizeof ( RECT ) ); // restore the old size to current size since the window is minimised 01160 } 01161 } 01162 } 01163 01164 01165 //-------------------------------------------------------------------------- 01166 // int SetRegValue(char *key_name, char *key_word, char *buffer,int dwType, int size) 01167 // 01168 // Function set the registry; if registary entry does not exist, it is 01169 // created. Actually, the key is created before it is set just to make sure 01170 // that is is there ! 01171 //-------------------------------------------------------------------------- 01172 01173 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size ) 01174 { 01175 int j = 0; 01176 01177 DWORD lpdwDisposition; 01178 HKEY hKey; 01179 01180 j = RegCreateKeyEx( 01181 HKEY_CURRENT_USER, 01182 key_name, 01183 0, // reserved 01184 NULL, // address of class string 01185 REG_OPTION_NON_VOLATILE, // special options flag 01186 KEY_WRITE, // desired security access 01187 NULL, // address of key security structure 01188 &hKey, // address of buffer for opened handle 01189 &lpdwDisposition // address of disposition value buffer 01190 ); 01191 01192 if ( j == ERROR_SUCCESS ) 01193 { 01194 RegSetValueEx( hKey, key_word, 0, dwType, buffer, size ); 01195 RegCloseKey( hKey ); 01196 } 01197 return ( j ); 01198 } 01199 01200 //-------------------------------------------------------------------------- 01201 // int GetRegValue(char *key_name, char *key_word, char *buffer, int size) 01202 // 01203 // Function reads the registry and gets a string value from it 01204 // buffer must be allocated by the caller, and the size is given in the size 01205 // paramater. 01206 // Return code is 1 for success, and 0 for failure. 01207 //-------------------------------------------------------------------------- 01208 01209 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size ) 01210 { 01211 int ret = 0; 01212 HKEY hKey; 01213 int dwType; 01214 int dwSize = size; 01215 01216 if ( RegOpenKeyEx( HKEY_CURRENT_USER, key_name, 0, KEY_READ, &hKey ) == ERROR_SUCCESS ) 01217 { 01218 if ( RegQueryValueEx( hKey, key_word, 0, (LPDWORD) &dwType, buffer, (LPDWORD) &dwSize ) == ERROR_SUCCESS ) 01219 { 01220 ret = 1; 01221 } 01222 RegCloseKey( hKey ); 01223 } 01224 return ( ret ); 01225 } 01226 01227 #ifdef PL_HAVE_FREETYPE 01228 01229 //-------------------------------------------------------------------------- 01230 // void plD_pixel_wingcc (PLStream *pls, short x, short y) 01231 // 01232 // callback function, of type "plD_pixel_fp", which specifies how a single 01233 // pixel is set in the current colour. 01234 //-------------------------------------------------------------------------- 01235 01236 static void plD_pixel_wingcc( PLStream *pls, short x, short y ) 01237 { 01238 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01239 01240 SetPixel( dev->hdc, x, y, dev->colour ); 01241 } 01242 01243 static void plD_pixelV_wingcc( PLStream *pls, short x, short y ) 01244 { 01245 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01246 01247 SetPixelV( dev->hdc, x, y, dev->colour ); 01248 } 01249 01250 //-------------------------------------------------------------------------- 01251 // void plD_set_pixelV_wingcc (PLStream *pls, short x, short y,PLINT colour) 01252 // 01253 // callback function, of type "plD_set_pixel_fp", which specifies how a 01254 // single pixel is set in the s[ecified colour. This colour 01255 // by-passes plplot's internal table, and directly 'hits the hardware'. 01256 //-------------------------------------------------------------------------- 01257 01258 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour ) 01259 { 01260 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01261 01262 SetPixel( dev->hdc, x, y, colour ); 01263 } 01264 01265 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour ) 01266 { 01267 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01268 01269 SetPixelV( dev->hdc, x, y, colour ); 01270 } 01271 01272 01273 //-------------------------------------------------------------------------- 01274 // void plD_read_pixel_wingcc (PLStream *pls, short x, short y) 01275 // 01276 // callback function, of type "plD_pixel_fp", which specifies how a single 01277 // pixel is read. 01278 //-------------------------------------------------------------------------- 01279 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y ) 01280 { 01281 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01282 01283 return ( GetPixel( dev->hdc, x, y ) ); 01284 } 01285 01286 01287 //-------------------------------------------------------------------------- 01288 // void init_freetype_lv1 (PLStream *pls) 01289 // 01290 // "level 1" initialisation of the freetype library. 01291 // "Level 1" initialisation calls plD_FreeType_init(pls) which allocates 01292 // memory to the pls->FT structure, then sets up the pixel callback 01293 // function. 01294 //-------------------------------------------------------------------------- 01295 01296 static void init_freetype_lv1( PLStream *pls ) 01297 { 01298 FT_Data *FT; 01299 int x; 01300 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01301 01302 plD_FreeType_init( pls ); 01303 01304 FT = (FT_Data *) pls->FT; 01305 01306 01307 01308 // 01309 // Work out if our device support "fast" pixel setting 01310 // and if so, use that instead of "slow" pixel setting 01311 // 01312 01313 x = GetDeviceCaps( dev->hdc, RASTERCAPS ); 01314 01315 if ( x & RC_BITBLT ) 01316 FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc; 01317 else 01318 FT->pixel = (plD_pixel_fp) plD_pixel_wingcc; 01319 01320 // 01321 // See if we have a 24 bit device (or better), in which case 01322 // we can use the better antialaaising. 01323 // 01324 01325 if ( GetDeviceCaps( dev->hdc, BITSPIXEL ) > 24 ) 01326 { 01327 FT->BLENDED_ANTIALIASING = 1; 01328 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_wingcc; 01329 01330 if ( x & RC_BITBLT ) 01331 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixelV_wingcc; 01332 else 01333 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_wingcc; 01334 } 01335 } 01336 01337 //-------------------------------------------------------------------------- 01338 // void init_freetype_lv2 (PLStream *pls) 01339 // 01340 // "Level 2" initialisation of the freetype library. 01341 // "Level 2" fills in a few setting that aren't public until after the 01342 // graphics sub-system has been initialised. 01343 // The "level 2" initialisation fills in a few things that are defined 01344 // later in the initialisation process for the GD driver. 01345 // 01346 // FT->scale is a scaling factor to convert co-ordinates. This is used by 01347 // the GD and other drivers to scale back a larger virtual page and this 01348 // eliminate the "hidden line removal bug". Set it to 1 if your device 01349 // doesn't have scaling. 01350 // 01351 // Some coordinate systems have zero on the bottom, others have zero on 01352 // the top. Freetype does it one way, and most everything else does it the 01353 // other. To make sure everything is working ok, we have to "flip" the 01354 // coordinates, and to do this we need to know how big in the Y dimension 01355 // the page is, and whether we have to invert the page or leave it alone. 01356 // 01357 // FT->ymax specifies the size of the page FT->invert_y=1 tells us to 01358 // invert the y-coordinates, FT->invert_y=0 will not invert the 01359 // coordinates. 01360 //-------------------------------------------------------------------------- 01361 01362 static void init_freetype_lv2( PLStream *pls ) 01363 { 01364 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01365 FT_Data *FT = (FT_Data *) pls->FT; 01366 01367 FT->scale = dev->scale; 01368 FT->ymax = dev->height; 01369 FT->invert_y = 1; 01370 01371 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) ) // do we want to at least *try* for smoothing ? 01372 { 01373 FT->ncol0_org = pls->ncol0; // save a copy of the original size of ncol0 01374 FT->ncol0_xtra = 16777216 - ( pls->ncol1 + pls->ncol0 ); // work out how many free slots we have 01375 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // find out how many different shades of anti-aliasing we can do 01376 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; // set a maximum number of shades 01377 plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) ); // redefine the size of cmap0 01378 // the level manipulations are to turn off the plP_state(PLSTATE_CMAP0) 01379 // call in plscmap0 which (a) leads to segfaults since the GD image is 01380 // not defined at this point and (b) would be inefficient in any case since 01381 // setcmap is always called later (see plD_bop_png) to update the driver 01382 // color palette to be consistent with cmap0. 01383 { 01384 PLINT level_save; 01385 level_save = pls->level; 01386 pls->level = 0; 01387 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); // call the function to add the extra cmap0 entries and calculate stuff 01388 pls->level = level_save; 01389 } 01390 FT->smooth_text = 1; // Yippee ! We had success setting up the extended cmap0 01391 } 01392 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 01393 { 01394 FT->smooth_text = 1; 01395 } 01396 } 01397 #endif 01398 01399 //-------------------------------------------------------------------------- 01400 // static void UpdatePageMetrics ( PLStream *pls, char flag ) 01401 // 01402 // UpdatePageMetrics is a simple function which simply gets new vales for 01403 // a changed DC, be it swapping from printer to screen or vice-versa. 01404 // The flag variable is used to tell the function if it is updating 01405 // from the printer (1) or screen (0). 01406 //-------------------------------------------------------------------------- 01407 01408 static void UpdatePageMetrics( PLStream *pls, char flag ) 01409 { 01410 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01411 #ifdef PL_HAVE_FREETYPE 01412 FT_Data *FT = (FT_Data *) pls->FT; 01413 #endif 01414 01415 if ( flag == 1 ) 01416 { 01417 dev->width = GetDeviceCaps( dev->hdc, HORZRES ); // Get the page size from the printer 01418 dev->height = GetDeviceCaps( dev->hdc, VERTRES ); 01419 } 01420 else 01421 { 01422 GetClientRect( dev->hwnd, &dev->rect ); 01423 dev->width = dev->rect.right; 01424 dev->height = dev->rect.bottom; 01425 } 01426 01427 if ( dev->width > dev->height ) // Work out the scaling factor for the 01428 { // "virtual" (oversized) page 01429 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width; 01430 } 01431 else 01432 { 01433 dev->scale = (PLFLT) PIXELS_Y / dev->height; 01434 } 01435 01436 #ifdef PL_HAVE_FREETYPE 01437 if ( FT ) // If we are using freetype, then set it up next 01438 { 01439 FT->scale = dev->scale; 01440 FT->ymax = dev->height; 01441 if ( GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_BITBLT ) 01442 FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc; 01443 else 01444 FT->pixel = (plD_pixel_fp) plD_pixel_wingcc; 01445 } 01446 #endif 01447 01448 pls->xdpi = GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4; 01449 pls->ydpi = GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4; 01450 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 ); 01451 plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) ); 01452 } 01453 01454 //-------------------------------------------------------------------------- 01455 // static void PrintPage ( PLStream *pls ) 01456 // 01457 // Function brings up a standard printer dialog and, after the user 01458 // has selected a printer, replots the current page to the windows 01459 // printer. 01460 //-------------------------------------------------------------------------- 01461 01462 static void PrintPage( PLStream *pls ) 01463 { 01464 wingcc_Dev *dev = (wingcc_Dev *) pls->dev; 01465 #ifdef PL_HAVE_FREETYPE 01466 FT_Data *FT = (FT_Data *) pls->FT; 01467 #endif 01468 PRINTDLG Printer; 01469 DOCINFO docinfo; 01470 01471 // 01472 // Reset the docinfo structure to 0 and set it's fields up 01473 // This structure is used to supply a name to the print queue 01474 // 01475 01476 ZeroMemory( &docinfo, sizeof ( docinfo ) ); 01477 docinfo.cbSize = sizeof ( docinfo ); 01478 docinfo.lpszDocName = _T( "Plplot Page" ); 01479 01480 // 01481 // Reset out printer structure to zero and initialise it 01482 // 01483 01484 ZeroMemory( &Printer, sizeof ( PRINTDLG ) ); 01485 Printer.lStructSize = sizeof ( PRINTDLG ); 01486 Printer.hwndOwner = dev->hwnd; 01487 Printer.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC; 01488 Printer.nCopies = 1; 01489 01490 // 01491 // Call the printer dialog function. 01492 // If the user has clicked on "Print", then we will continue 01493 // processing and print out the page. 01494 // 01495 01496 if ( PrintDlg( &Printer ) != 0 ) 01497 { 01498 // 01499 // Before doing anything, we will take some backup copies 01500 // of the existing values for page size and the like, because 01501 // all we are going to do is a quick and dirty modification 01502 // of plplot's internals to match the new page size and hope 01503 // it all works out ok. After that, we will manip the values, 01504 // and when all is done, restore them. 01505 // 01506 01507 if ( ( dev->push = GlobalAlloc( GMEM_ZEROINIT, sizeof ( wingcc_Dev ) ) ) != NULL ) 01508 { 01509 BusyCursor(); 01510 memcpy( dev->push, dev, sizeof ( wingcc_Dev ) ); 01511 01512 dev->hdc = dev->PRNT_hdc = Printer.hDC; // Copy the printer HDC 01513 01514 UpdatePageMetrics( pls, 1 ); 01515 01516 #ifdef PL_HAVE_FREETYPE 01517 if ( FT ) // If we are using freetype, then set it up next 01518 { 01519 dev->FT_smooth_text = FT->smooth_text; // When printing, we don't want smoothing 01520 FT->smooth_text = 0; 01521 } 01522 #endif 01523 01524 // 01525 // Now the stuff that actually does the printing !! 01526 // 01527 01528 StartDoc( dev->hdc, &docinfo ); 01529 plRemakePlot( pls ); 01530 EndDoc( dev->hdc ); 01531 01532 // 01533 // Now to undo everything back to what it was for the screen 01534 // 01535 01536 dev->hdc = dev->SCRN_hdc; // Reset the screen HDC to the default 01537 UpdatePageMetrics( pls, 0 ); 01538 01539 #ifdef PL_HAVE_FREETYPE 01540 if ( FT ) // If we are using freetype, then set it up next 01541 { 01542 FT->smooth_text = dev->FT_smooth_text; 01543 } 01544 #endif 01545 memcpy( dev, dev->push, sizeof ( wingcc_Dev ) ); // POP our "stack" now to restore the values 01546 01547 GlobalFree( dev->push ); 01548 NormalCursor(); 01549 RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW ); 01550 } 01551 } 01552 } 01553 01554 01555 01556 #else 01557 int 01558 pldummy_wingcc() 01559 { 01560 return ( 0 ); 01561 } 01562 01563 #endif // PLD_wingccdev