1 /*****************************************************************************
2 ** Copyright (C) 1998-2001 Ljubomir Milanovic & Horst Wagner
3 ** This file is part of the g2 library
5 ** This library is free software; you can redistribute it and/or
6 ** modify it under the terms of the GNU Lesser General Public
7 ** License as published by the Free Software Foundation; either
8 ** version 2.1 of the License, or (at your option) any later version.
10 ** This library is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ** Lesser General Public License for more details.
15 ** You should have received a copy of the GNU Lesser General Public
16 ** License along with this library; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ******************************************************************************/
25 #include "g2_device.h"
27 #include "g2_config.h"
30 #include "g2_win32_P.h"
31 #include "g2_win32_funix.h"
35 /* Global Definitions */
36 int g2_win32_registered = FALSE;
37 HINSTANCE g2res_DLL; /* Instance of the resource DLL */
39 #define PDP ((struct g2_win32_STRUCT *)pdp)
42 #define PI 3.14159265358979323846
45 #define sgn(x) (x>0?1:x?-1:0)
47 /* someday their might be a DLL version of g2 */
49 BOOL WINAPI DllMain( HANDLE hModule, DWORD fdwreason, LPVOID lpReserved )
52 case DLL_PROCESS_ATTACH:
53 // The DLL is being mapped into process's address space
54 // Do any required initialization on a per application basis, return FALSE if failed
55 MessageBox(NULL, "DLL Process Attach", "DLL Message 1", MB_OK);
57 case DLL_THREAD_ATTACH:
58 // A thread is created. Do any required initialization on a per thread basis
59 MessageBox(NULL, "DLL Thread Attach", "DLL Message 1", MB_OK);
61 case DLL_THREAD_DETACH:
62 // Thread exits with cleanup
63 MessageBox(NULL, "DLL Thread Detach", "DLL Message 1", MB_OK);
65 case DLL_PROCESS_DETACH:
66 // The DLL unmapped from process's address space. Do necessary cleanup
67 MessageBox(NULL, "DLL Process Detach", "DLL Message 1", MB_OK);
70 MessageBox(NULL, "DLL default", "DLL Message 1", MB_OK);
78 g2_win32_SetPen(int pid, void *pdp)
82 logBrush.lbStyle = PS_SOLID;
83 logBrush.lbColor = PDP->Inks[PDP->Pen];
84 logBrush.lbHatch = 0 ;
87 PDP->hPen = ExtCreatePen (logBrush.lbStyle | PS_GEOMETRIC |
88 PS_ENDCAP_FLAT | PS_JOIN_BEVEL | (PDP->PenStyle > 0)*PS_USERSTYLE,
89 PDP->PenWidth, &logBrush,
90 PDP->PenStyle , PDP->PenDash) ;
91 if (PDP->hPen != NULL)
93 SelectObject(PDP->hMemDC,PDP->hPen);
94 /* if (PDP->type == g2_win32)*/
99 errhandler("Pen",NULL);
103 oldpen = PDP->hNullPen;
104 PDP->hNullPen = CreatePen(PS_SOLID,1,PDP->Inks[PDP->Pen]);
105 if (PDP->hNullPen != NULL)
107 /* if (PDP->type == g2_win32)*/
108 DeleteObject(oldpen);
112 errhandler("Pen",NULL);
113 PDP->hNullPen = oldpen;
120 int g2_win32_Cleanup(int pid, void *pdp)
122 struct g2_win32_STRUCT *thispdp;
125 g2_win32_ClearPalette(pid,pdp);
126 if (PDP->hBrush != NULL) DeleteObject(PDP->hBrush);
127 if (PDP->hPen != NULL) DeleteObject(PDP->hPen);
128 if (PDP->hNullPen != NULL) DeleteObject(PDP->hPen);
129 if (PDP->hFont != NULL) DeleteObject(PDP->hFont);
130 if (PDP->hBitmap != NULL) DeleteObject(PDP->hBitmap);
131 if (PDP->hMemDC != NULL) DeleteDC(PDP->hMemDC);
132 if (PDP->PenDash != NULL) free(PDP->PenDash);
139 int g2_win32_Delete(int pid, void *pdp)
144 SendMessage(PDP->hwndThreadWindow,WM_CLOSE,(WPARAM)NULL,(LPARAM)NULL);
148 CloseEnhMetaFile(PDP->hMemDC);
149 g2_win32_Cleanup(pid,pdp);
157 int g2_win32_Clear(int pid, void *pdp)
162 g2_win32_Pen(pid,pdp,PDP->BkColor);
163 g2_win32_FilledRectangle(pid,pdp,0,0,PDP->nWidth,PDP->nHeight);
164 g2_win32_Pen(pid,pdp,OldPen);
168 int g2_win32_Flush(int pid, void *pdp)
170 InvalidateRect(PDP->hwndThreadWindow, (RECT *)NULL, TRUE);
174 int g2_win32_Pen(int pid, void *pdp, int color)
176 struct tagLOGBRUSH logbrush;
179 if(color>=PDP->NoOfInks || color<0)
181 fprintf(stderr,"g2_WIN32: Ink %d not defined\n",color);
186 PDP->PenColor = PDP->Inks[color];
187 g2_win32_SetPen(pid,pdp);
189 logbrush.lbStyle = BS_SOLID;
190 logbrush.lbColor = PDP->PenColor;
191 oldbrush = PDP->hBrush;
192 PDP->hBrush = CreateBrushIndirect(&logbrush);
193 if (PDP->hBrush == NULL)
195 errhandler("Pen (CreateBrush)",NULL);
196 PDP->hBrush = oldbrush;
199 /* if (PDP->type == g2_win32)*/
200 DeleteObject(oldbrush);
204 int g2_win32_Ink(int pid, void *pdp, double red, double green, double blue)
208 rc = (BYTE)((int)(red*255));
209 gc = (BYTE)((int)(green*255));
210 bc = (BYTE)((int)(blue*255));
215 PDP->Inks=(COLORREF *)malloc(PDP->NoOfInks*sizeof(COLORREF));
217 PDP->Inks=(COLORREF *)realloc((void *)PDP->Inks,PDP->NoOfInks*sizeof(COLORREF));
221 fputs("g2: not enough memory\n",stderr);
225 PDP->Inks[PDP->NoOfInks-1]=RGB(rc,gc,bc);
226 return PDP->NoOfInks-1;
230 int g2_win32_ClearPalette(int pid, void *pdp)
232 if (PDP->Inks != NULL)
240 int g2_win32_SetBackground(int pid, void *pdp, int color)
242 PDP->BkColor = color;
243 SetBkColor(PDP->hMemDC,PDP->BkColor);
247 int g2_win32_SetLineWidth(int pid, void *pdp, int w)
250 g2_win32_SetPen(pid,pdp);
254 int g2_win32_SetDash(int pid, void *pdp, int n, int *data)
256 if (PDP->PenDash != NULL)
263 PDP->PenDash = (DWORD *)malloc(n*sizeof(DWORD));
265 PDP->PenDash[i] = data[i];
267 g2_win32_SetPen(pid,pdp);
272 int g2_win32_SetFontSize(int pid, void *pdp, int size)
274 //static LOGFONT lf = {10,0,0,0,0,0,0,0,0,0,0,0,0,"Arial\0"};
277 oldfont = PDP->hFont;
278 //lf.lfHeight = size;
279 //PDP->hFont = CreateFontIndirect(&lf);
280 PDP->hFont = CreateFont(-size, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, OUT_TT_ONLY_PRECIS , 0, PROOF_QUALITY,0, "Times New Roman\0");
281 if (PDP->hFont == NULL)
283 errhandler("Font (CreateFont)",NULL);
284 PDP->hFont = oldfont;
288 SelectObject(PDP->hMemDC,PDP->hFont);
289 if (oldfont != NULL)// && PDP->type == g2_win32)
290 DeleteObject(oldfont);
295 int g2_win32_Plot(int pid, void *pdp, int x, int y)
297 return SetPixel(PDP->hMemDC,x,y,PDP->PenColor);
300 int g2_win32_Line(int pid, void *pdp, int x1, int y1, int x2, int y2)
302 MoveToEx(PDP->hMemDC,x1,y1,NULL);
303 LineTo(PDP->hMemDC,x2,y2);
304 SetPixel(PDP->hMemDC,x1,y1,PDP->PenColor);
305 SetPixel(PDP->hMemDC,x2,y2,PDP->PenColor);
306 // specifically draw end points since windows does not include one endpoint
310 int g2_win32_PolyLine(int pid, void *pdp, int N, int *points)
315 PointList = (POINT *)malloc(N*sizeof(POINT));
316 if (PointList == NULL)
318 fprintf(stderr,"g2_win32: not enough memory !\n");
323 PointList[i].x = points[2*i];
324 PointList[i].y = points[2*i+1];
326 Polyline(PDP->hMemDC,PointList,N);
333 int g2_win32_Rectangle(int pid, void *pdp, int x, int y, int x2, int y2)
335 SelectObject(PDP->hMemDC,GetStockObject(NULL_BRUSH));
336 Rectangle(PDP->hMemDC,x,y,x2+1,y2+1); // add one since windows excludes lower right point
340 int g2_win32_FilledRectangle(int pid, void *pdp, int x1, int y1, int x2, int y2)
342 SelectObject(PDP->hMemDC,PDP->hBrush);
343 SelectObject(PDP->hMemDC,PDP->hNullPen);
344 return Rectangle(PDP->hMemDC,x1,y1,x2+1,y2+1); // add one since windows excludes lower right point
345 SelectObject(PDP->hMemDC,PDP->hPen);
349 int g2_win32_Polygon(int pid, void *pdp, int N, int *points)
353 PointList = (POINT *)malloc(N*sizeof(POINT));
354 if (PointList == NULL)
356 fprintf(stderr,"g2: not enough memory !\n");
361 PointList[i].x = points[2*i];
362 PointList[i].y = points[2*i+1];
364 SelectObject(PDP->hMemDC,GetStockObject(NULL_BRUSH));
365 Polygon(PDP->hMemDC,PointList,N);
370 int g2_win32_FilledPolygon(int pid, void *pdp, int N, int *points)
374 PointList = (POINT *)malloc(N*sizeof(POINT));
375 if (PointList == NULL)
377 fprintf(stderr,"g2: not enough memory !\n");
382 PointList[i].x = points[2*i];
383 PointList[i].y = points[2*i+1];
385 SelectObject(PDP->hMemDC,PDP->hBrush);
386 SelectObject(PDP->hMemDC,PDP->hNullPen);
387 Polygon(PDP->hMemDC,PointList,N);
388 SelectObject(PDP->hMemDC,PDP->hPen);
393 int g2_win32_Ellipse(int pid, void *pdp, int x, int y, int r1, int r2)
395 SelectObject(PDP->hMemDC,GetStockObject(NULL_BRUSH));
396 return Ellipse(PDP->hMemDC,x-r1,y-r2,x+r1+1,y+r2+1); // add one since windows is end exclusive
399 int g2_win32_FilledEllipse(int pid, void *pdp, int x, int y, int r1, int r2)
401 SelectObject(PDP->hMemDC,PDP->hBrush);
402 SelectObject(PDP->hMemDC,PDP->hNullPen);
403 return Ellipse(PDP->hMemDC,x-r1,y-r2,x+r1+1,y+r2+1); // add one since windows is end exclusive
404 SelectObject(PDP->hMemDC,PDP->hPen);
408 int g2_win32_Arc(int pid, void *pdp, int x, int y, int r1, int r2, double a1, double a2)
412 SelectObject(PDP->hMemDC,GetStockObject(NULL_BRUSH));
413 if (PDP->type == g2_win32)
414 return Arc(PDP->hMemDC,x-r1,y-r2,x+r1,y+r2,dtoi(x+r1*cos(a1)),dtoi(y-r2*sin(a1)),dtoi(x+r1*cos(a2)),dtoi(y-r2*sin(a2)));
416 return Arc(PDP->hMemDC,x-r1,y-r2,x+r1,y+r2,dtoi(x+r1*cos(a2)),dtoi(y-r2*sin(a2)),dtoi(x+r1*cos(a1)),dtoi(y-r2*sin(a1)));
419 int g2_win32_FilledArc(int pid, void *pdp, int x, int y, int r1, int r2, double a1, double a2)
423 SelectObject(PDP->hMemDC,PDP->hBrush);
424 SelectObject(PDP->hMemDC,PDP->hNullPen);
425 if (PDP->type == g2_win32)
426 Pie(PDP->hMemDC,x-r1,y-r2,x+r1,y+r2,dtoi(x+r1*cos(a1)),dtoi(y-r2*sin(a1)),dtoi(x+r1*cos(a2)),dtoi(y-r2*sin(a2)));
428 Pie(PDP->hMemDC,x-r1,y-r2,x+r1,y+r2,dtoi(x+r1*cos(a2)),dtoi(y-r2*sin(a2)),dtoi(x+r1*cos(a1)),dtoi(y-r2*sin(a1)));
429 SelectObject(PDP->hMemDC,PDP->hPen);
433 int g2_win32_DrawString(int pid, void *pdp, int x, int y, const char *text)
435 SetTextColor(PDP->hMemDC,PDP->PenColor);
436 SetBkMode(PDP->hMemDC,TRANSPARENT);
437 return TextOut(PDP->hMemDC,x,y,text,strlen(text));
440 int g2_win32_QueryPointer(int pid, void *pdp, int *x, int *y, unsigned int *button)
442 // Thanks to input by Martin stéphane
447 GetCursorPos(&point);
449 ScreenToClient(PDP->hwndThreadWindow,&point);
455 if (PDP->hwndThreadWindow != GetForegroundWindow())
456 return; // return if our window does not have the focus
458 if (GetKeyState(VK_LBUTTON)<0)
461 if (GetKeyState(VK_MBUTTON)<0)
464 if (GetKeyState(VK_RBUTTON)<0)
465 *button=*button+1024;
470 void errhandler(LPSTR errtxt,HWND hwnd)
472 LPVOID lpMessageBuffer;
476 LastError = GetLastError();
478 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,
479 NULL,LastError,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
480 (LPTSTR) &lpMessageBuffer,0,NULL );
482 sprintf(szError,"Error in %s\n Error code %d : %s\n" ,errtxt,LastError,lpMessageBuffer);
483 MessageBox(hwnd,szError,"error",MB_OK);
485 LocalFree( lpMessageBuffer );
489 int InitApplication()
493 // Fill in window class structure with parameters that describe the
496 g2res_DLL = LoadLibrary("g2res.dll");
498 if (g2res_DLL == NULL)
499 printf("Warning: Could not load g2 resource DLL\n Menu and Icon are disabled\n");
502 wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
503 wc.lpfnWndProc = g2_WndProc; // Function to retrieve messages for windows of this class.
504 wc.cbClsExtra = 0; // No per-class extra data.
505 wc.cbWndExtra = 0; // No per-window extra data.
506 wc.hInstance = 0; // Application that owns the class.
508 if (g2res_DLL != NULL)
510 wc.hIcon = LoadIcon(g2res_DLL, MAKEINTRESOURCE(IDI_ICON1));
511 if (wc.hIcon == NULL)
512 errhandler("Error in LoadIcon",NULL);
514 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
515 wc.hbrBackground = NULL;
516 wc.lpszMenuName = "G2WIN32";
517 wc.lpszClassName = "g2Window"; // Name used in call to CreateWindow.
519 /* Register the window class and return success/failure code. */
522 if(!RegisterClass(&wc))
524 errhandler("RegisterClass",NULL);
527 g2_win32_registered = TRUE;
534 * \defgroup win32 MS Windows
539 * Create a Windows device.
541 * \param width window width
542 * \param height window height
543 * \param title window title
544 * \param type window type, see ::g2_win32_type
546 * \return physical device id
550 int g2_open_win32(int width, int height, const char *title, int type)
555 g2_win32_STRUCT *pdp;
557 pdp = (g2_win32_STRUCT *)malloc(sizeof(g2_win32_STRUCT));
564 PDP->PenColor = RGB(1,1,1);
567 PDP->nHeight = height;
568 PDP->messageloop = 0;
574 if(g2_win32_registered == FALSE)
582 PDP->title = "g2 Window";
583 PDP->hThread = CreateThread(NULL, 0,
584 (LPTHREAD_START_ROUTINE)g2_StartThread,
587 (LPDWORD) &ThreadID );
589 if (PDP->hThread == NULL)
590 fprintf(stderr,"g2_win32: Thread could not be started\n");
592 SetThreadPriority(PDP->hThread,THREAD_PRIORITY_ABOVE_NORMAL);
593 //Wait till window is created by Thread
594 while( PDP->messageloop == 0)
603 RECT Rect = { 0, 0, 0, 0 };
604 TCHAR szDesc[] = "Created by g2\0\0";
606 float PixelsX, PixelsY, MMX, MMY;
608 dwInchesX = PDP->nWidth/72;
609 dwInchesY = PDP->nHeight/72;
610 // dwInchesX x dwInchesY in .01mm units
611 SetRect( &Rect, 0, 0,dwInchesX*2540, dwInchesY*2540 );
613 // Get a Reference DC
614 hScreenDC = GetDC( NULL );
616 // Get the physical characteristics of the reference DC
617 PixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );
618 PixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );
619 MMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );
620 MMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );
622 // Create the Metafile
623 PDP->hMemDC = CreateEnhMetaFile(hScreenDC, title, &Rect, szDesc);
624 //tstDC = CreateEnhMetaFile(hScreenDC, "test.emf", &Rect, szDesc);
626 // Release the reference DC
627 ReleaseDC( NULL, hScreenDC );
628 // Anisotropic mapping mode
629 SetMapMode( PDP->hMemDC, MM_ANISOTROPIC );
630 // Set the Windows extent
631 SetWindowExtEx( PDP->hMemDC, dwInchesX*dwDPI, dwInchesY*dwDPI, NULL );
633 // Set the viewport extent to reflect
634 // dwInchesX" x dwInchesY" in device units
635 SetViewportExtEx( PDP->hMemDC,
636 (int)((float)dwInchesX*25.4f*PixelsX/MMX),
637 (int)((float)dwInchesY*25.4f*PixelsY/MMY),
639 // printf("viewport: %d %d\n",(int)((float)dwInchesX*25.4f*PixelsX/MMX),
640 // (int)((float)dwInchesY*25.4f*PixelsY/MMY));
641 // create the device context
642 // PDP->hMemDC = CreateMetaFile(NULL) ;
644 // PDP->hMemDC = CreateEnhMetaFile( (HDC)NULL, title, &WmfRect, "Created by g2");
645 // PDP->hMemDC = CreateMetaFile(title);
646 // SetMapMode(PDP->hMemDC,MM_LOMETRIC );
647 // SetWindowExtEx(PDP->hMemDC,width,height,NULL);
648 // SetViewportExtEx(PDP->hMemDC,width*1000,height*1000,NULL);
649 if (PDP->hMemDC == NULL) errhandler("Could not Create Metafile !\n",NULL);
650 SetArcDirection(PDP->hMemDC,AD_CLOCKWISE);
656 SetTextAlign(PDP->hMemDC,TA_BOTTOM | TA_LEFT);
657 vid = g2_register_physical_device(pid, pdp,
658 g2_IntCoor, g2_win32_funix,
662 g2_allocate_basic_colors(vid);
664 g2_set_background(vid, 0);
665 g2_set_font_size(vid, 10);