• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

wingcc.c

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

Generated on Wed Oct 12 2011 20:42:23 for PLplot by  doxygen 1.7.1