30 #if !defined ( __CYGWIN__ )
34 #define _T( a ) __TEXT( a )
43 #define ARRAY_SIZE( x ) ( ( sizeof x ) / ( sizeof *x ) )
44 #define INITIAL_HEAP_SIZE 16384 // Initial size of heap in bytes
80 struct _font_entry *next;
96 enum _dev_viewer viewer;
98 enum _dev_state state;
99 enum _dev_state prev_state;
103 unsigned int status_bar : 1;
104 unsigned int menu_bar : 1;
127 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wingdi =
"wingdi:Windows GDI:1:wingdi:11:wingdi\n";
130 static int wingdi_streams = 0;
133 static TCHAR * frame_window_class_name = _T(
"PLplotFrame" );
134 static WNDCLASSEX frame_window_class;
137 static TCHAR * plot_area_class_name = _T(
"PLplotArea" );
138 static WNDCLASSEX plot_area_class;
141 static HMENU plot_popup_menu;
144 static HANDLE wingdi_heap;
147 struct _font_entry *font_list = NULL;
155 static void plD_line_wingdi(
PLStream *,
short,
short,
short,
short );
156 static void plD_polyline_wingdi(
PLStream *,
short *,
short *,
PLINT );
157 static void plD_fill_polygon_wingdi(
PLStream *
pls );
160 static void plD_eop_wingdi(
PLStream * );
161 static void plD_bop_wingdi(
PLStream * );
162 static void plD_tidy_wingdi(
PLStream * );
163 static void plD_wait_wingdi(
PLStream * );
169 CommandPrint = 0x08A1,
170 CommandNextPage = 0x08A2,
173 #define PlotAreaId 0x08F0
174 #define StatusBarId 0x08F1
178 #ifndef ENABLE_DYNDRIVERS
196 CrossHairCursor(
struct wingdi_Dev * dev )
200 cursor = LoadCursor( NULL, IDC_CROSS );
201 SetClassLongPtr( dev->plot, GCL_HCURSOR, (
long) cursor );
202 return SetCursor( cursor );
206 NormalCursor(
struct wingdi_Dev * dev )
210 cursor = LoadCursor( NULL, IDC_ARROW );
211 SetClassLongPtr( dev->plot, GCL_HCURSOR, (LONG_PTR) cursor );
216 BusyCursor(
struct wingdi_Dev * dev )
220 cursor = LoadCursor( NULL, IDC_WAIT );
221 SetClassLongPtr( dev->plot, GCL_HCURSOR, (LONG_PTR) cursor );
226 update_status_bar(
struct wingdi_Dev * dev )
228 LPSTR status_text[] =
237 if ( dev->status_bar == NULL )
240 SendMessage( dev->status_bar,
243 (LPARAM) status_text[dev->state] );
254 static void UpdatePageMetrics(
PLStream *
pls,
enum _dev_type dev_type )
256 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
258 dev->type = dev_type;
259 if ( dev_type == DEV_PRINTER )
263 PLFLT plot_aspect, print_aspect;
264 hsize = GetDeviceCaps( dev->hdc, HORZRES );
265 vsize = GetDeviceCaps( dev->hdc, VERTRES );
269 plot_aspect = (
PLFLT) dev->width / (
PLFLT) dev->height;
271 if ( plot_aspect > 1.0 )
275 dev->height = (
PLINT) ( (
PLFLT) hsize / plot_aspect );
280 dev->width = (
PLINT) ( (
PLFLT) vsize * plot_aspect );
288 GetClientRect( dev->plot, &rect );
289 dev->width = rect.right;
290 dev->height = rect.bottom;
292 pldebug(
"wingdi",
"Page size [%d %d] [%d %d]\n",
294 rect.right, rect.bottom );
304 pldebug(
"wingdi",
"Scale = (%f %f) (FLT)\n",
305 dev->xscale, dev->yscale );
310 pldebug(
"wingdi",
"Original xdpi = %f ydpi = %f\n",
318 pls->
xdpi = GetDeviceCaps( dev->hdc, LOGPIXELSX );
319 dev->xdpmm = pls->
xdpi / 25.4;
320 pls->
ydpi = GetDeviceCaps( dev->hdc, LOGPIXELSY );
321 dev->ydpmm = pls->
ydpi / 25.4;
323 pldebug(
"wingdi",
"New xdpi = %f ydpi = %f\n",
325 pldebug(
"wingdi",
"Windows reports xdpi = %d ydpi = %d\n",
326 GetDeviceCaps( dev->hdc, LOGPIXELSX ),
327 GetDeviceCaps( dev->hdc, LOGPIXELSY ) );
331 dev->yscale * pls->
ydpi / 25.4 );
346 static void PrintPage(
PLStream *pls )
348 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
352 struct wingdi_Dev *push;
356 ZeroMemory( &docinfo,
sizeof ( docinfo ) );
357 docinfo.cbSize =
sizeof ( docinfo );
358 docinfo.lpszDocName = _T(
"Plplot Page" );
363 hDevMode = GlobalAlloc( GHND,
sizeof ( DEVMODE ) );
364 if ( hDevMode == NULL )
366 plwarn(
"wingdi: Failed to allocate memory for printer defaults\n" );
369 ZeroMemory( hDevMode,
sizeof ( DEVMODE ) );
370 hDevMode->dmSpecVersion = DM_SPECVERSION;
371 hDevMode->dmSize =
sizeof ( DEVMODE );
372 hDevMode->dmFields = DM_ORIENTATION;
373 hDevMode->dmOrientation = DMORIENT_LANDSCAPE;
376 ZeroMemory( &Printer,
sizeof ( PRINTDLGEX ) );
377 Printer.lStructSize =
sizeof ( PRINTDLGEX );
378 Printer.hwndOwner = dev->plot;
379 Printer.hDevMode = hDevMode;
382 Printer.Flags = PD_NOPAGENUMS | PD_NOCURRENTPAGE | PD_NOSELECTION
383 | PD_COLLATE | PD_RETURNDC;
390 Printer.nPageRanges = 0;
391 Printer.nMaxPageRanges = 0;
392 Printer.lpPageRanges = NULL;
393 Printer.nMinPage = 0;
394 Printer.nMaxPage = 0;
399 Printer.nStartPage = START_PAGE_GENERAL;
404 if ( PrintDlgEx( &Printer ) == S_OK
405 && Printer.dwResultAction == PD_RESULT_PRINT )
413 push = HeapAlloc( wingdi_heap, 0,
sizeof (
struct wingdi_Dev ) );
419 memcpy( push, dev,
sizeof (
struct wingdi_Dev ) );
422 dev->hdc = Printer.hDC;
423 UpdatePageMetrics( pls, DEV_PRINTER );
426 StartDoc( dev->hdc, &docinfo );
431 memcpy( dev, push,
sizeof (
struct wingdi_Dev ) );
432 UpdatePageMetrics( pls, DEV_WINDOW );
434 HeapFree( wingdi_heap, 0, push );
445 plwarn(
"wingdi: Unable to save state for print" );
450 if ( Printer.hDC != NULL )
451 DeleteDC( Printer.hDC );
452 if ( Printer.hDevMode != NULL )
453 DeleteDC( Printer.hDevMode );
454 if ( Printer.hDevNames != NULL )
455 DeleteDC( Printer.hDevNames );
458 GlobalFree( hDevMode );
462 wait_for_user_input(
PLStream *pls )
464 struct wingdi_Dev * dev = (
struct wingdi_Dev *) pls->
dev;
467 pldebug(
"wingdi",
"Waiting for user input\n" );
470 dev->state = DEV_WAITING;
471 update_status_bar( dev );
474 while ( GetMessage( &msg, NULL, 0, 0 ) && dev->state != DEV_ACTIVE )
476 TranslateMessage( &msg );
477 switch ( (
int) msg.message )
481 TrackPopupMenu( plot_popup_menu,
482 TPM_CENTERALIGN | TPM_RIGHTBUTTON,
483 LOWORD( msg.lParam ),
484 HIWORD( msg.lParam ),
491 if ( ( (TCHAR) ( msg.wParam ) == 32 ) ||
492 ( (TCHAR) ( msg.wParam ) == 13 ) )
494 dev->state = DEV_ACTIVE;
495 update_status_bar( dev );
497 else if ( ( (TCHAR) ( msg.wParam ) == 27 ) ||
498 ( (TCHAR) ( msg.wParam ) ==
'q' ) ||
499 ( (TCHAR) ( msg.wParam ) ==
'Q' ) )
501 dev->state = DEV_ACTIVE;
502 update_status_bar( dev );
503 PostQuitMessage( 0 );
507 case WM_LBUTTONDBLCLK:
508 pldebug(
"wingdi",
"WM_LBUTTONDBLCLK\n" );
509 dev->state = DEV_ACTIVE;
510 update_status_bar( dev );
514 switch ( LOWORD( msg.wParam ) )
517 pldebug(
"wingdi",
"CommandPrint\n" );
520 case CommandNextPage:
521 pldebug(
"wingdi",
"CommandNextPage\n" );
522 dev->state = DEV_ACTIVE;
523 update_status_bar( dev );
526 pldebug(
"wingdi",
"CommandQuit\n" );
527 dev->state = DEV_ACTIVE;
528 update_status_bar( dev );
529 PostQuitMessage( 0 );
535 DispatchMessage( &msg );
540 pldebug(
"wingdi",
"Done waiting\n" );
541 dev->state = DEV_ACTIVE;
553 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
559 previous = CrossHairCursor( dev );
561 while ( gin->
pX < 0 )
563 GetMessage( &msg, NULL, 0, 0 );
564 TranslateMessage( &msg );
565 switch ( (
int) msg.message )
570 gin->
dX = (
PLFLT) gin->
pX / ( dev->width - 1 );
571 gin->
dY = 1.0 - (
PLFLT) gin->
pY / ( dev->height - 1 );
573 if ( msg.wParam & MK_LBUTTON )
575 pldebug(
"wingdi",
"Left button down\n" );
581 else if ( msg.wParam & MK_MBUTTON )
583 pldebug(
"wingdi",
"Middle button down\n" );
588 else if ( msg.wParam & MK_RBUTTON )
590 pldebug(
"wingdi",
"Right button down\n" );
600 gin->
dX = (
PLFLT) gin->
pX / ( dev->width - 1 );
601 gin->
dY = 1.0 - (
PLFLT) gin->
pY / ( dev->height - 1 );
603 if ( msg.wParam & MK_LBUTTON )
605 pldebug(
"wingdi",
"Left button up\n" );
610 else if ( msg.wParam & MK_MBUTTON )
612 pldebug(
"wingdi",
"Middle button up\n" );
615 gin->
state = 0x10000;
617 else if ( msg.wParam & MK_RBUTTON )
619 pldebug(
"wingdi",
"Right button up\n" );
629 gin->
dX = (
PLFLT) gin->
pX / ( dev->width - 1 );
630 gin->
dY = 1.0 - (
PLFLT) gin->
pY / ( dev->height - 1 );
641 SetCursor( previous );
650 static void CopySCRtoBMP(
PLStream *pls )
652 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
657 if ( dev->hdc_bmp != NULL )
658 DeleteDC( dev->hdc_bmp );
659 if ( dev->bitmap != NULL )
660 DeleteObject( dev->bitmap );
662 dev->hdc_bmp = CreateCompatibleDC( dev->hdc );
663 GetClientRect( dev->plot, &rect );
664 dev->bitmap = CreateCompatibleBitmap( dev->hdc,
665 rect.right, rect.bottom );
666 previous = SelectObject( dev->hdc_bmp, dev->bitmap );
667 BitBlt( dev->hdc_bmp, 0, 0, rect.right, rect.bottom, dev->hdc, 0, 0, SRCCOPY );
668 SelectObject( dev->hdc_bmp, previous );
679 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
680 COLORREF previous_color;
683 pldebug(
"wingdi",
" Erasing window\n" );
689 if ( dev->type == DEV_WINDOW )
692 GetClientRect( dev->plot, &rect );
693 previous_color = SetBkColor( dev->hdc,
695 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &rect, _T(
"" ), 0, 0 );
696 SetBkColor( dev->hdc, previous_color );
702 rect.right = GetDeviceCaps( dev->hdc, HORZRES );
703 rect.bottom = GetDeviceCaps( dev->hdc, VERTRES );
717 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
719 enum _dev_state current;
721 pldebug(
"wingdi",
"Resizing\n" );
724 if ( dev->state == DEV_WAITING
725 || dev->state == DEV_ACTIVE
726 || dev->state == DEV_DRAWING )
728 GetClientRect( dev->plot, &rect );
729 pldebug(
"wingdi",
" Size = [%d %d] [%d %d]\n",
731 rect.right, rect.bottom );
734 if ( ( rect.right > 0 ) && ( rect.bottom > 0 ) )
736 UpdatePageMetrics( pls, DEV_WINDOW );
740 current = dev->state;
742 dev->state = current;
743 update_status_bar( dev );
748 pldebug(
"wingdi",
" No action taken, state = %d\n", dev->state );
750 pldebug(
"wingdi",
"Resizing done\n" );
756 LRESULT CALLBACK PlplotFrameProc(
762 struct wingdi_Dev *dev = NULL;
766 dev = (
struct wingdi_Dev *) GetWindowLongPtr( hwnd, GWLP_USERDATA );
768 dev = (
struct wingdi_Dev *) GetWindowLongPtr( hwnd, GWL_USERDATA );
779 hStatus = CreateWindowEx(
783 WS_CHILD | WS_VISIBLE,
787 GetModuleHandle( NULL ),
789 if ( hStatus != NULL )
791 int status_widths[] = { 100, 200, 300, -1 };
793 SendMessage( hStatus, SB_SETPARTS,
794 (WPARAM) ARRAY_SIZE( status_widths ),
795 (LPARAM) status_widths );
796 SendMessage( hStatus, SB_SETTEXT,
798 (LPARAM) (LPSTR) TEXT(
"Active" ) );
802 MessageBox( hwnd,
"Could not create status bar.",
803 "Error", MB_OK | MB_ICONERROR );
813 RECT rStatus, rFrame;
817 GetClientRect( hwnd, &rFrame );
820 hStatus = GetDlgItem( hwnd, StatusBarId );
821 SendMessage( hStatus, WM_SIZE, 0, 0 );
822 GetWindowRect( hStatus, &rStatus );
825 hPlot = GetDlgItem( hwnd, PlotAreaId );
826 plot_height = rFrame.bottom - ( rStatus.bottom - rStatus.top );
830 rFrame.right, plot_height,
831 SWP_NOZORDER | SWP_SHOWWINDOW );
843 return DefWindowProc( hwnd, uMsg, wParam, lParam );
854 LRESULT CALLBACK PlplotPlotAreaProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
857 struct wingdi_Dev *dev = NULL;
861 if ( nMsg == WM_CREATE )
869 pls = (
PLStream *) GetWindowLongPtr( hwnd, GWLP_USERDATA );
871 pls = (
PLStream *) GetWindowLongPtr( hwnd, GWL_USERDATA );
878 return DefWindowProc( hwnd, nMsg, wParam, lParam );
881 dev = (
struct wingdi_Dev *) pls->
dev;
896 pldebug(
"wingdi",
"WM_DESTROY\n" );
897 PostQuitMessage( 0 );
909 pldebug(
"wingdi",
"WM_PAINT state = %d\n", dev->state );
915 if ( GetUpdateRect( dev->plot, NULL,
FALSE ) )
922 BeginPaint( dev->plot, &ps );
924 pldebug(
"wingdi",
" Need to redraw area (%d,%d) (%d,%d)\n",
925 ps.rcPaint.left, ps.rcPaint.top,
926 ps.rcPaint.right, ps.rcPaint.bottom );
927 pldebug(
"wingdi",
" Erase status = %d\n", ps.fErase );
928 pldebug(
"wingdi",
" Device state = %d\n", dev->state );
936 if ( dev->bitmap != NULL && dev->state != DEV_DRAWING )
939 pldebug(
"wingdi",
" Blit image\n" );
940 previous = SelectObject( dev->hdc_bmp, dev->bitmap );
942 ps.rcPaint.left, ps.rcPaint.top,
943 ps.rcPaint.right, ps.rcPaint.bottom,
945 ps.rcPaint.left, ps.rcPaint.top,
947 SelectObject( dev->hdc_bmp, previous );
952 " No paint action bitmap = %lx state = \n",
953 dev->bitmap, dev->state );
956 EndPaint( dev->plot, &ps );
961 pldebug(
"wingdi",
" No update area to paint\n" );
963 pldebug(
"wingdi",
"WM_PAINT exit\n" );
969 pldebug(
"wingdi",
"WM_SIZE wParam = %d\n", wParam );
972 if ( wParam == SIZE_MAXIMIZED )
975 pldebug(
"wingdi",
" Window maximized\n" );
978 else if ( dev->state == DEV_SIZEMOVE )
982 pldebug(
"wingdi",
" Window size/moved\n" );
986 dev->state = DEV_RESIZE;
987 pldebug(
"wingdi",
" New state %d\n", dev->state );
988 update_status_bar( dev );
990 else if ( wParam == SIZE_RESTORED )
995 pldebug(
"wingdi",
" Window restored\n" );
1000 pldebug(
"wingdi",
" Unknowing sizing action\n" );
1002 pldebug(
"wingdi",
"WM_SIZE exit\n" );
1007 case WM_ENTERSIZEMOVE:
1008 pldebug(
"wingdi",
"WM_ENTERSIZEMOVE\n" );
1009 pldebug(
"wingdi",
" Save state %d\n", dev->state );
1010 dev->prev_state = dev->state;
1012 dev->state = DEV_SIZEMOVE;
1013 update_status_bar( dev );
1017 case WM_EXITSIZEMOVE:
1018 pldebug(
"wingdi",
"WM_EXITSIZEMOVE\n" );
1021 if ( dev->state == DEV_RESIZE || dev->state == DEV_SIZEMOVE )
1023 pldebug(
"wingdi",
" Restore state %d\n", dev->prev_state );
1027 dev->state = dev->prev_state;
1028 update_status_bar( dev );
1039 pldebug(
"wingdi",
"WM_ERASEBKGND state = %d\n", dev->state );
1041 if ( dev->state != DEV_WAITING )
1049 pldebug(
"wingdi",
" No erase action taken\n" );
1059 xw = GET_X_LPARAM( lParam );
1060 yw = GET_Y_LPARAM( lParam );
1061 x = (double) xw * dev->xscale;
1062 y = (
double) ( dev->height - yw ) * dev->yscale;
1064 snprintf( mesg,
sizeof ( mesg ),
"%5.1lf", x );
1065 if ( dev->status_bar != NULL )
1066 SendMessage( dev->status_bar,
1071 snprintf( mesg,
sizeof ( mesg ),
"%5.1lf", y );
1072 if ( dev->status_bar != NULL )
1073 SendMessage( dev->status_bar,
1084 pldebug(
"wingdi",
"WM_COMMAND\n" );
1091 return DefWindowProc( hwnd, nMsg, wParam, lParam );
1101 wingdi_module_initialize(
void )
1103 INITCOMMONCONTROLSEX init_controls;
1110 if ( wingdi_streams++ > 0 )
1113 pldebug(
"wingdi",
"module init\n" );
1116 init_controls.dwSize =
sizeof ( INITCOMMONCONTROLSEX );
1117 init_controls.dwICC = ICC_BAR_CLASSES;
1118 if ( !InitCommonControlsEx( &init_controls ) )
1120 plwarn(
"wingdi: Failed to initialize common Window controls\n" );
1128 memset( &frame_window_class, 0,
sizeof ( WNDCLASSEX ) );
1131 frame_window_class.lpszClassName = frame_window_class_name;
1135 frame_window_class.cbSize =
sizeof ( WNDCLASSEX );
1138 frame_window_class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS
1142 frame_window_class.lpfnWndProc = PlplotFrameProc;
1145 frame_window_class.hInstance = GetModuleHandle( NULL );
1148 frame_window_class.hIcon = LoadIcon( NULL, IDI_APPLICATION );
1149 frame_window_class.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
1150 frame_window_class.hCursor = LoadCursor( NULL, IDC_ARROW );
1153 frame_window_class.hbrBackground = (HBRUSH) COLOR_WINDOW;
1156 frame_window_class.cbWndExtra =
sizeof (
struct wingdi_Dev * );
1159 RegisterClassEx( &frame_window_class );
1166 memset( &plot_area_class, 0,
sizeof ( WNDCLASSEX ) );
1169 plot_area_class.lpszClassName = plot_area_class_name;
1173 plot_area_class.cbSize =
sizeof ( WNDCLASSEX );
1176 plot_area_class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS
1180 plot_area_class.lpfnWndProc = PlplotPlotAreaProc;
1183 plot_area_class.hInstance = GetModuleHandle( NULL );
1186 plot_area_class.hIcon = LoadIcon( NULL, IDI_APPLICATION );
1187 plot_area_class.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
1188 plot_area_class.hCursor = LoadCursor( NULL, IDC_ARROW );
1191 plot_area_class.hbrBackground = NULL;
1195 plot_area_class.cbWndExtra =
sizeof (
PLStream * );
1198 RegisterClassEx( &plot_area_class );
1203 plot_popup_menu = CreatePopupMenu();
1204 AppendMenu( plot_popup_menu, MF_STRING, CommandPrint, _T(
"Print" ) );
1205 AppendMenu( plot_popup_menu, MF_STRING, CommandNextPage, _T(
"Next Page" ) );
1206 AppendMenu( plot_popup_menu, MF_STRING, CommandQuit, _T(
"Quit" ) );
1214 wingdi_heap = HeapCreate( 0, INITIAL_HEAP_SIZE, 0 );
1215 if ( wingdi_heap == NULL )
1219 plexit(
"wingdi: Unable to allocate heap" );
1223 static void wingdi_module_cleanup(
void )
1225 struct _font_entry *ptr;
1228 if ( wingdi_streams > 0 )
1231 DeleteMenu( plot_popup_menu, CommandPrint, 0 );
1232 DeleteMenu( plot_popup_menu, CommandNextPage, 0 );
1233 DeleteMenu( plot_popup_menu, CommandQuit, 0 );
1234 DestroyMenu( plot_popup_menu );
1236 if ( !UnregisterClass( plot_area_class_name, plot_area_class.hInstance ) )
1238 plexit(
"wingdi: Failed to unregister window class" );
1240 if ( !UnregisterClass( frame_window_class_name, frame_window_class.hInstance ) )
1242 plexit(
"wingdi: Failed to unregister window class" );
1245 while ( font_list != NULL )
1248 DeleteObject( ptr->font );
1249 font_list = ptr->next;
1250 HeapFree( wingdi_heap, 0, ptr );
1253 if ( HeapDestroy( wingdi_heap ) == 0 )
1255 plexit(
"wingdi: Failed to destroy heap" );
1268 struct wingdi_Dev *dev;
1270 int full_viewer = 0;
1271 DrvOpt wingdi_options[] = {
1272 {
"full",
DRV_INT, &full_viewer,
"Enable full function viewer (0|1)" },
1273 {
"statusbar",
DRV_INT, &status_bar,
"Enable status bar (0|1)" },
1282 pldebug(
"wingdi",
"Device Init\n" );
1285 wingdi_module_initialize();
1288 if ( pls->
dev != NULL )
1289 free( (
void *) pls->
dev );
1291 pls->
dev = calloc( 1, (
size_t)
sizeof (
struct wingdi_Dev ) );
1292 if ( pls->
dev == NULL )
1293 plexit(
"plD_init_wingdi_Dev: Out of memory." );
1296 dev = (
struct wingdi_Dev *) pls->
dev;
1318 dev->viewer = VIEWER_FULL;
1320 dev->viewer = VIEWER_MINIMAL;
1324 dev->feature.status_bar = 1;
1326 dev->feature.status_bar = 0;
1334 plspage( 0., 0., 800, 600, 0, 0 );
1337 dev->width = pls->
xlength - 1;
1338 dev->height = pls->
ylength - 1;
1342 programlength = strlen( pls->
program ) + 1;
1343 program = malloc( programlength *
sizeof ( TCHAR ) );
1344 MultiByteToWideChar( CP_UTF8, 0, pls->
program, programlength, program, programlength );
1349 if ( dev->viewer == VIEWER_FULL )
1352 dev->frame = CreateWindowEx(
1353 WS_EX_WINDOWEDGE + WS_EX_LEFT,
1354 frame_window_class_name,
1364 frame_window_class.hInstance,
1369 dev->plot = CreateWindowEx(
1371 plot_area_class_name,
1373 WS_CHILD | WS_VISIBLE,
1377 plot_area_class.hInstance,
1384 dev->plot = CreateWindowEx(
1385 WS_EX_WINDOWEDGE + WS_EX_LEFT,
1386 plot_area_class_name,
1396 plot_area_class.hInstance,
1401 if ( dev->plot == NULL )
1403 plexit(
"wingdi: Failed to create plot area\n" );
1414 SetWindowLongPtr( dev->plot, GWLP_USERDATA, (LONG_PTR) pls );
1416 SetWindowLongPtr( dev->frame, GWLP_USERDATA, (LONG_PTR) dev );
1418 SetWindowLongPtr( dev->plot, GWL_USERDATA, (LONG) pls );
1420 SetWindowLongPtr( dev->frame, GWL_USERDATA, (LONG) dev );
1424 dev->hdc = GetDC( dev->plot );
1432 if ( dev->viewer == VIEWER_FULL )
1434 ShowWindow( dev->frame, SW_SHOWDEFAULT );
1435 SetForegroundWindow( dev->frame );
1439 ShowWindow( dev->plot, SW_SHOWDEFAULT );
1440 SetForegroundWindow( dev->plot );
1443 if ( dev->feature.status_bar )
1447 dev->status_bar = GetDlgItem( dev->frame, StatusBarId );
1454 UpdatePageMetrics( pls, DEV_WINDOW );
1459 SetPolyFillMode( dev->hdc, ALTERNATE );
1461 SetPolyFillMode( dev->hdc, WINDING );
1467 dev->state = DEV_ACTIVE;
1468 update_status_bar( dev );
1478 plD_line_wingdi(
PLStream *pls,
short x1a,
short y1a,
short x2a,
short y2a )
1480 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
1481 HGDIOBJ previous_obj;
1484 points[0].x = (LONG) ( x1a / dev->xscale );
1485 points[1].x = (LONG) ( x2a / dev->xscale );
1486 points[0].y = (LONG) ( dev->height - ( y1a / dev->yscale ) );
1487 points[1].y = (LONG) ( dev->height - ( y2a / dev->yscale ) );
1489 previous_obj = SelectObject( dev->hdc, dev->pen );
1491 if ( points[0].x != points[1].x || points[0].y != points[1].y )
1493 Polyline( dev->hdc, points, 2 );
1497 SetPixel( dev->hdc, points[0].x, points[0].y, dev->color );
1499 SelectObject( dev->hdc, previous_obj );
1509 plD_polyline_wingdi(
PLStream *pls,
short *xa,
short *ya,
PLINT npts )
1511 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
1513 POINT *points = NULL;
1514 HGDIOBJ previous_obj;
1518 points = HeapAlloc( wingdi_heap, HEAP_ZERO_MEMORY,
1519 (
size_t) npts *
sizeof ( POINT ) );
1520 if ( points != NULL )
1522 for ( i = 0; i < npts; i++ )
1524 points[i].x = (LONG) ( xa[i] / dev->xscale );
1525 points[i].y = (LONG) ( dev->height - ( ya[i] / dev->yscale ) );
1528 previous_obj = SelectObject( dev->hdc, dev->pen );
1529 Polyline( dev->hdc, points, npts );
1530 SelectObject( dev->hdc, previous_obj );
1531 HeapFree( wingdi_heap, 0, points );
1535 plexit(
"Could not allocate memory to \"plD_polyline_wingdi\"\n" );
1546 plD_fill_polygon_wingdi(
PLStream *pls )
1548 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
1550 POINT *points = NULL;
1551 HGDIOBJ previous_brush, previous_pen;
1559 points = HeapAlloc( wingdi_heap, HEAP_ZERO_MEMORY,
1560 (
size_t) pls->
dev_npts * sizeof ( POINT ) );
1562 if ( points == NULL )
1563 plexit(
"Could not allocate memory to \"plD_fill_polygon_wingdi\"\n" );
1565 for ( i = 0; i < pls->
dev_npts; i++ )
1567 points[i].x = (
PLINT) ( pls->
dev_x[i] / dev->xscale );
1568 points[i].y = (
PLINT) ( dev->height - ( pls->
dev_y[i] / dev->yscale ) );
1572 fillbrush = CreateSolidBrush( dev->color );
1573 hpen = CreatePen( PS_SOLID, 1, dev->color );
1574 previous_brush = SelectObject( dev->hdc, fillbrush );
1575 previous_pen = SelectObject( dev->hdc, hpen );
1578 Polygon( dev->hdc, points, pls->
dev_npts );
1581 SelectObject( dev->hdc, previous_brush );
1582 DeleteObject( fillbrush );
1583 SelectObject( dev->hdc, previous_pen );
1584 DeleteObject( hpen );
1586 HeapFree( wingdi_heap, 0, points );
1597 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
1598 COLORREF previous_color;
1601 if ( x1 >= 0 && y1 >= 0 && x2 >= 0 && y2 >= 0 )
1603 rect.left = (LONG) ( x1 / dev->xscale );
1604 rect.top = (LONG) ( dev->height - ( y1 / dev->yscale ) );
1605 rect.right = (LONG) ( x2 / dev->xscale );
1606 rect.bottom = (LONG) ( dev->height - ( y2 / dev->yscale ) );
1611 GetClientRect( dev->plot, &rect );
1617 previous_color = SetBkColor( dev->hdc,
1619 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &rect, _T(
"" ), 0, 0 );
1620 SetBkColor( dev->hdc, previous_color );
1634 PLFLT rotation, shear, stride;
1638 PLFLT old_sscale, sscale;
1639 PLFLT old_soffset, soffset;
1649 set_font(
struct wingdi_Dev * dev,
1650 LONG font_height, LONG escapement,
1651 LONG weight, BYTE italic,
1653 BYTE pitch, BYTE family )
1655 struct _font_entry *ptr = font_list;
1657 for ( ptr = font_list; ptr != NULL; ptr = ptr->next )
1660 ptr->info.lfHeight == font_height
1661 && ptr->info.lfEscapement == escapement
1662 && ptr->info.lfWeight == weight
1663 && ptr->info.lfItalic == italic
1664 && ptr->info.lfCharSet == charset
1665 && ptr->info.lfPitchAndFamily == ( pitch | family )
1666 && ptr->hdc == dev->hdc
1669 return SelectObject( dev->hdc, ptr->font );
1674 ptr = HeapAlloc( wingdi_heap, 0,
sizeof (
struct _font_entry ) );
1677 ptr->info.lfHeight = font_height;
1678 ptr->info.lfWidth = 0;
1679 ptr->info.lfEscapement = escapement;
1680 ptr->info.lfOrientation = 0;
1681 ptr->info.lfWeight = weight;
1682 ptr->info.lfItalic = italic;
1683 ptr->info.lfUnderline = 0;
1684 ptr->info.lfStrikeOut = 0;
1685 ptr->info.lfCharSet = charset;
1686 ptr->info.lfOutPrecision = OUT_OUTLINE_PRECIS;
1687 ptr->info.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1688 ptr->info.lfQuality = ANTIALIASED_QUALITY;
1689 ptr->info.lfPitchAndFamily = pitch | family;
1690 ptr->font = CreateFontIndirect( &( ptr->info ) );
1691 ptr->hdc = dev->hdc;
1694 if ( ptr->font == NULL )
1696 plwarn(
"wingdi: Unable to create a font, using default\n" );
1697 HeapFree( wingdi_heap, 0, ptr );
1702 if ( font_list != NULL )
1704 ptr->next = font_list;
1713 return SelectObject( dev->hdc, ptr->font );
1718 static const char hershey_to_ansi_lookup[] =
1720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1723 0, 0, 0,
'!',
'"',
'#',
'$',
'%',
'&',
'\'',
1724 '(',
')',
'*',
'+',
',',
'-',
'.',
'/',
'0',
'1',
1725 '2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
':',
';',
1726 '<',
'=',
'>',
'?',
'@',
'A',
'B',
'C',
'D',
'E',
1727 'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
1728 'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
1729 'Z',
'[',
'\\',
']',
'^',
'_',
'`',
'a',
'b',
'c',
1730 'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
1731 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
1732 'x',
'y',
'z',
'{',
'|',
'}',
'~', 0, 0, 0,
1734 static const char hershey_to_symbol_lookup[] =
1736 0, 0xB7, 0x2B, 0x2A, 0, 0, 0, 0, 0, 0,
1737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1738 0, 0, 0, 0, 0, 0, 0, 0, 0xAC, 0xAE,
1743 process_text_escape(
struct wingdi_Dev *dev,
EscText *args,
1744 int *i,
char *
buffer,
int *j,
1745 struct _text_state *state )
1750 switch ( args->
string[++( *i )] )
1754 &state->old_sscale, &state->sscale,
1755 &state->old_soffset, &state->soffset );
1758 (LONG) ( state->font_height * state->sscale ),
1759 (LONG) ( state->rotation ),
1762 state->font_charset,
1763 state->font_pitch, state->font_family );
1767 &state->old_sscale, &state->sscale,
1768 &state->old_soffset, &state->soffset );
1771 (LONG) ( state->font_height * state->sscale ),
1772 (LONG) ( state->rotation ),
1775 state->font_charset,
1776 state->font_pitch, state->font_family );
1779 switch ( args->
string[++( *i )] )
1782 state->font_family = FF_SWISS;
1784 state->font_charset = ANSI_CHARSET;
1787 state->font_family = FF_ROMAN;
1789 state->font_charset = ANSI_CHARSET;
1792 state->font_family = FF_ROMAN;
1794 state->font_charset = ANSI_CHARSET;
1797 state->font_family = FF_SCRIPT;
1799 state->font_charset = ANSI_CHARSET;
1803 (LONG) ( state->font_height * state->sscale ),
1804 (LONG) ( state->rotation ),
1807 state->font_charset,
1808 state->font_pitch, state->font_family );
1811 state->font_family = FF_DONTCARE;
1813 state->font_charset = GREEK_CHARSET;
1816 (LONG) ( state->font_height * state->sscale ),
1817 (LONG) ( state->rotation ),
1820 state->font_charset,
1821 state->font_pitch, state->font_family );
1824 sscanf( args->
string + *i,
"%d", &val );
1826 if ( val > 0 && val < ARRAY_SIZE( hershey_to_ansi_lookup )
1827 && hershey_to_ansi_lookup[val] != 0 )
1829 buffer[( *j )++] = hershey_to_ansi_lookup[val];
1833 plwarn(
"Unsupported hershey character\n" );
1835 buffer[( *j )++] = 0x95;
1840 plwarn(
"Unicode characters are not supported\n" );
1844 plwarn(
"Ignoring escape code %c\n" );
1857 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
1858 struct _text_state state;
1859 PLFLT cos_rot, sin_rot;
1860 PLFLT cos_shear, sin_shear;
1862 UINT halign, valign;
1863 HFONT font = NULL, prev_font = NULL;
1864 COLORREF prev_color;
1874 state.font_weight = FW_NORMAL;
1875 state.font_charset = ANSI_CHARSET;
1876 state.font_pitch = DEFAULT_PITCH;
1877 state.font_family = FF_DONTCARE;
1878 switch ( pls->
cfont )
1882 state.font_family = FF_SWISS;
1886 state.font_family = FF_ROMAN;
1890 state.font_family = FF_ROMAN;
1895 state.font_family = FF_SCRIPT;
1900 state.font_height = 1.6 * pls->
chrht * dev->ydpmm;
1903 &state.rotation, &state.shear, &state.stride );
1904 state.rotation -= pls->
diorot *
PI / 2.0;
1905 cos_rot = (
PLFLT) cos( state.rotation );
1906 sin_rot = (
PLFLT) sin( state.rotation );
1907 cos_shear = (
PLFLT) cos( state.shear );
1908 sin_shear = (
PLFLT) sin( state.shear );
1911 state.rotation = state.rotation * ( 180.0 /
M_PI ) * 10.0;
1919 PLFLT cos_theta, sin_theta;
1926 cos_theta = cos( -pls->
diorot *
PI / 2.0 );
1927 sin_theta = sin( -pls->
diorot *
PI / 2.0 );
1928 x = cos_theta * (
PLFLT) ox - sin_theta * (
PLFLT) oy;
1929 y = sin_theta * (
PLFLT) ox + cos_theta * (
PLFLT) oy;
1936 rx = (
int) ( x / dev->xscale );
1937 ry = (
int) ( dev->height - ( y / dev->yscale ) );
1941 rx = (int) ( args->
x / dev->xscale );
1942 ry = (int) ( dev->height - ( args->
y / dev->yscale ) );
1949 if ( args->
base == 2 )
1954 else if ( args->
base == 1 )
1965 ry -= (int) ( 0.5 * pls->
chrht * dev->ydpmm );
1970 if ( args->
just < 0.499 )
1975 else if ( args->
just > 0.501 )
1985 prev_font = set_font( dev,
1986 (LONG) state.font_height,
1987 (LONG) state.rotation,
1992 state.font_family );
1993 prev_color = SetTextColor( dev->hdc, dev->color );
1994 prev_bkmode = SetBkMode( dev->hdc, TRANSPARENT );
2001 int height = 0, width = 0;
2006 len = strlen( args->
string );
2007 buffer = HeapAlloc( wingdi_heap, 0, ( len + 1 ) *
sizeof (
char ) );
2008 if ( buffer == NULL )
2010 plexit(
"wingdi: Unable to allocate character buffer\n" );
2018 for ( i = j = 0; i < len + 1; i++ )
2020 if ( args->
string[i] != esc && args->
string[i] !=
'\0' )
2024 buffer[j++] = args->
string[i];
2026 else if ( i != len && args->
string[i + 1] == esc )
2030 buffer[j++] = args->
string[i];
2044 GetTextExtentPoint32( dev->hdc,
2052 width += segment_size.cx;
2053 if ( segment_size.cy > height )
2054 height = segment_size.cy;
2060 process_text_escape( dev, args,
2068 if ( text_segments > 1 )
2070 UINT save_text_align;
2084 rx -= (int) ( cos_rot * 0.5 * (
PLFLT) width );
2085 ry += (int) ( sin_rot * 0.5 * (
PLFLT) width );
2088 save_text_align = SetTextAlign( dev->hdc, TA_LEFT | valign );
2092 for ( i = j = 0; i < len + 1; i++ )
2094 if ( args->
string[i] != esc && args->
string[i] !=
'\0' )
2098 buffer[j++] = args->
string[i];
2100 else if ( i != len && args->
string[i + 1] == esc )
2104 buffer[j++] = args->
string[i];
2117 GetTextExtentPoint32( dev->hdc,
2122 sx = (int) ( ( 1.0 - cos_rot ) * (
PLFLT) state.soffset );
2123 sy = (int) ( ( 1.0 - sin_rot ) * (
PLFLT) state.soffset );
2130 rx += (int) ( cos_rot * (
PLFLT) segment_size.cx );
2131 ry -= (int) ( sin_rot * (
PLFLT) segment_size.cx );
2136 process_text_escape( dev, args,
2142 HeapFree( wingdi_heap, 0, buffer );
2149 if ( text_segments == 1 )
2155 UINT save_text_align;
2157 save_text_align = SetTextAlign( dev->hdc, halign | valign );
2163 SetTextAlign( dev->hdc, save_text_align );
2167 if ( prev_font != NULL )
2168 SelectObject( dev->hdc, prev_font );
2169 SetTextColor( dev->hdc, prev_color );
2170 SetBkMode( dev->hdc, prev_bkmode );
2179 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
2181 pldebug(
"wingdi",
"End of the page\n" );
2183 if ( dev->type == DEV_WINDOW )
2185 CopySCRtoBMP( pls );
2187 EndPage( dev->hdc );
2190 NormalCursor( dev );
2193 dev->state = DEV_ACTIVE;
2202 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
2203 pldebug(
"wingdi",
"Start of Page\n" );
2206 dev->state = DEV_DRAWING;
2209 update_status_bar( dev );
2214 if ( dev->type == DEV_WINDOW )
2220 SendMessage( dev->plot,
2227 StartPage( dev->hdc );
2240 struct wingdi_Dev *dev = NULL;
2242 pldebug(
"wingdi",
"plD_tidy_wingdi\n" );
2244 if ( pls->
dev != NULL )
2246 dev = (
struct wingdi_Dev *) pls->
dev;
2248 if ( dev->hdc != NULL )
2249 ReleaseDC( dev->plot, dev->hdc );
2251 if ( dev->bitmap != NULL )
2252 DeleteObject( dev->bitmap );
2254 if ( dev->plot != NULL )
2255 DestroyWindow( dev->plot );
2256 if ( dev->status_bar != NULL )
2257 DestroyWindow( dev->status_bar );
2258 if ( dev->frame != NULL )
2259 DestroyWindow( dev->frame );
2263 wingdi_module_cleanup();
2276 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
2279 wait_for_user_input( pls );
2291 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
2306 if ( dev->pen != NULL )
2307 DeleteObject( dev->pen );
2308 dev->pen = CreatePen( PS_SOLID, (
int) pls->
width, dev->color );
2317 #ifndef PLESC_TELLME
2327 void *roomformore[6];
2330 #define PLESC_TELLME 41
2336 struct wingdi_Dev *dev = (
struct wingdi_Dev *) pls->
dev;
2345 plD_fill_polygon_wingdi( pls );
2349 plD_clear_wingdi( pls,
2355 plD_text_wingdi( pls, (
EscText *) ptr );
2365 if ( *(
PLINT *) ( ptr ) == 0 )
2366 SetROP2( dev->hdc, R2_COPYPEN );
2368 SetROP2( dev->hdc, R2_XORPEN );
2417 struct passmeup *pup = ptr;
2419 pup->hwnd = &( dev->plot );
2420 pup->hdc = &( dev->hdc );
2433 #endif // PLD_wingdidev
int plParseDrvOpts(DrvOpt *acc_opt)
void plP_script_scale(PLBOOL ifupper, PLINT *level, PLFLT *old_scale, PLFLT *scale, PLFLT *old_offset, PLFLT *offset)
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
void plexit(PLCHAR_VECTOR errormsg)
void(* plD_eop_fp)(struct PLStream_struct *)
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
void(* plD_tidy_fp)(struct PLStream_struct *)
#define PLESC_DOUBLEBUFFERING
void plGinInit(PLGraphicsIn *gin)
void(* plD_wait_fp)(struct PLStream_struct *)
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
void(* plD_bop_fp)(struct PLStream_struct *)
#define PLESC_END_RASTERIZE
static PLCHAR_VECTOR program
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
#define PLDLLIMPEXP_DRIVER
static PLStream * pls[PL_NSTREAMS]
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
void plRotationShear(PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride)
unsigned short unicode_array_len
void plRemakePlot(PLStream *pls)
#define PLESC_START_RASTERIZE
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wingdi(PLDispatchTable *pdt)
void plwarn(PLCHAR_VECTOR errormsg)
plD_polyline_fp pl_polyline
void(* plD_init_fp)(struct PLStream_struct *)