]> git.mxchange.org Git - simgear.git/blob - simgear/screen/win32-printer.h
Mac OS X fixes from Markus Morawitz
[simgear.git] / simgear / screen / win32-printer.h
1
2 class CGlPrinter
3 {
4 public:
5         typedef enum { RENDER_TO_PRINTER, RENDER_TO_BITMAP, READ_BITMAP, PRINT_BITMAP } PRINTMODE;
6 public:
7         inline CGlPrinter( PRINTMODE mode = READ_BITMAP );
8         inline ~CGlPrinter();
9         inline bool Begin( char *title, int w=0, int h=0 );
10         inline void End( GLubyte *bm=NULL );
11         inline double GetAspect();
12         inline int GetHorzRes();
13         inline int GetVertRes();
14
15 private:
16         PRINTMODE m_printMode;
17         PRINTDLG m_printDLG;
18         BITMAPINFO m_bitmapInfo;
19         void *m_bitmap;
20         HBITMAP bitmapHandle;
21         HDC m_bitmapDC;
22         HGLRC m_printerHGLRC;
23         HGLRC m_bitmapHGLRC;
24         int m_pageWidth;                                // Dimension of printer page (x)
25         int m_pageHeight;                               // Dimension of printer page (y)
26 };
27
28 inline double CGlPrinter::GetAspect()
29 {
30         return (double)m_pageWidth/(double)m_pageHeight;
31 }
32
33 inline int CGlPrinter::GetHorzRes()
34 {
35         return m_pageWidth;
36 }
37
38 inline int CGlPrinter::GetVertRes()
39 {
40         return m_pageHeight;
41 }
42
43 inline CGlPrinter::CGlPrinter( PRINTMODE mode ) :
44         m_printerHGLRC( 0 ), m_bitmapHGLRC( 0 ), m_printMode( mode ), m_bitmap( NULL )
45 {
46 }
47
48 inline CGlPrinter::~CGlPrinter()
49 {
50 }
51
52 inline bool CGlPrinter::Begin( char *title, int w, int h  )
53 {
54         // Pixel format for Printer Device context
55         static PIXELFORMATDESCRIPTOR pPrintfd = {
56                 sizeof(PIXELFORMATDESCRIPTOR),                  // Size of this structure
57                 1,                                      // Version of this structure    
58                 PFD_DRAW_TO_WINDOW |                    // Draw to Window (not to m_bitmap)
59                 PFD_SUPPORT_OPENGL |                    // Support OpenGL calls 
60                 PFD_SUPPORT_GDI |                       // Allow GDI drawing in window too
61                 PFD_DEPTH_DONTCARE,                                             // Don't care about depth buffering
62                 PFD_TYPE_RGBA,                          // RGBA Color mode
63                 24,                                     // Want 24bit color 
64                 0,0,0,0,0,0,                            // Not used to select mode
65                 0,0,                                    // Not used to select mode
66                 0,0,0,0,0,                              // Not used to select mode
67                 0,                                      // Size of depth buffer
68                 0,                                      // Not used to select mode
69                 0,                                      // Not used to select mode
70                 0,                                                      // Not used to select mode
71                 0,                                      // Not used to select mode
72                 0,0,0 };                                // Not used to select mode
73
74         DOCINFO docInfo;        // Document Info
75         int nPixelFormat;               // Pixel format requested
76
77         // Get printer information
78         memset(&m_printDLG,0,sizeof(PRINTDLG));
79         m_printDLG.lStructSize = sizeof(PRINTDLG);
80         m_printDLG.hwndOwner = GetForegroundWindow();
81         m_printDLG.hDevMode = NULL;
82         m_printDLG.hDevNames = NULL;
83         m_printDLG.Flags = PD_RETURNDC | PD_ALLPAGES;
84
85         // Display printer dialog
86         if(!PrintDlg(&m_printDLG))
87         {
88                 printf( "PrintDlg() failed %lx\n", GetLastError() );
89                 return false;
90         }
91
92         // Get the dimensions of the page
93         m_pageWidth = GetDeviceCaps(m_printDLG.hDC, HORZRES);
94         m_pageHeight = GetDeviceCaps(m_printDLG.hDC, VERTRES);
95
96         // Initialize DocInfo structure
97         docInfo.cbSize = sizeof(DOCINFO);
98         docInfo.lpszDocName = title;
99         docInfo.lpszOutput = NULL;
100
101
102         // Choose a pixel format that best matches that described in pfd
103         nPixelFormat = ChoosePixelFormat(m_printDLG.hDC, &pPrintfd);
104         // Watch for no pixel format available for this printer
105         if(nPixelFormat == 0)
106                 {
107                 // Delete the printer context
108                 DeleteDC(m_printDLG.hDC);
109
110                 printf( "ChoosePixelFormat() failed %lx\n", GetLastError() );
111                 return false;
112                 }
113
114         // Start the document and page
115         StartDoc(m_printDLG.hDC, &docInfo);
116         StartPage(m_printDLG.hDC);
117         
118         // Set the pixel format for the device context, but watch for failure
119         if(!SetPixelFormat(m_printDLG.hDC, nPixelFormat, &pPrintfd))
120                 {
121                 // Delete the printer context
122                 DeleteDC(m_printDLG.hDC);
123
124                 printf( "SetPixelFormat() failed %lx\n", GetLastError() );
125                 return false;
126                 }
127
128         // Create the Rendering context and make it current
129         if ( m_printMode == RENDER_TO_PRINTER )
130         {
131                 m_printerHGLRC = wglCreateContext(m_printDLG.hDC);
132                 wglMakeCurrent(m_printDLG.hDC, m_printerHGLRC);
133         }
134         else 
135         {
136                 memset( &m_bitmapInfo, 0, sizeof(BITMAPINFO) );
137                 m_bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
138                 if ( m_printMode == READ_BITMAP )
139                 {
140                         GLint vp[4];
141                         glGetIntegerv( GL_VIEWPORT, vp );
142                         m_bitmapInfo.bmiHeader.biWidth = vp[2];
143                         m_bitmapInfo.bmiHeader.biHeight = (vp[3] + 3) & ~3;
144                 }
145                 else
146                 {
147                         if ( m_printMode == RENDER_TO_BITMAP )
148                         {
149                                 m_bitmapInfo.bmiHeader.biWidth = m_pageWidth;
150                                 m_bitmapInfo.bmiHeader.biHeight = m_pageHeight;
151                         }
152                         else
153                         {
154                                 // PRINT_BITMAP
155                                 m_bitmapInfo.bmiHeader.biWidth = w;
156                                 m_bitmapInfo.bmiHeader.biHeight = h;
157                         }
158                 }
159                 m_bitmapInfo.bmiHeader.biPlanes = 1;
160                 m_bitmapInfo.bmiHeader.biBitCount = 24;
161                 m_bitmapInfo.bmiHeader.biCompression = BI_RGB;
162                 m_bitmapInfo.bmiHeader.biSizeImage = m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*3;
163                 m_bitmapInfo.bmiHeader.biXPelsPerMeter = 2952; // 75dpi
164                 m_bitmapInfo.bmiHeader.biYPelsPerMeter = 2952; // 75dpi
165                 m_bitmapInfo.bmiHeader.biClrUsed = 0;
166                 m_bitmapInfo.bmiHeader.biClrImportant = 0;
167                 bitmapHandle = CreateDIBSection( NULL, &m_bitmapInfo, DIB_RGB_COLORS, &m_bitmap, NULL, 0);
168                 m_bitmapDC = CreateCompatibleDC( NULL );
169                 if ( m_bitmapDC == NULL )
170                 {
171                         DeleteDC(m_printDLG.hDC);
172                         printf( "CreateCompatibleDC() failed %lx\n", GetLastError() );
173                         return false;
174                 }
175                 if ( SelectObject( m_bitmapDC, bitmapHandle ) == NULL )
176                 {
177                         DeleteDC(m_printDLG.hDC);
178                         DeleteDC(m_bitmapDC);
179                         printf( "SelectObject() failed %lx\n", GetLastError() );
180                         return false;
181                 }
182                 PIXELFORMATDESCRIPTOR pfd;
183                 memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
184                 pfd.nVersion = 1 ;
185                 pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
186                 pfd.iPixelType = PFD_TYPE_RGBA ; 
187                 pfd.cColorBits = 24;
188                 pfd.iLayerType = PFD_MAIN_PLANE;
189                 int pixelFormat = ::ChoosePixelFormat(m_bitmapDC, &pfd);
190                 SetPixelFormat (m_bitmapDC, pixelFormat, &pfd);
191                 if ( m_printMode == RENDER_TO_BITMAP )
192                 {
193                         m_bitmapHGLRC = wglCreateContext( m_bitmapDC );
194                         wglMakeCurrent( m_bitmapDC, m_bitmapHGLRC );
195                 }
196         }
197
198         if ( m_printMode == RENDER_TO_PRINTER || m_printMode == RENDER_TO_BITMAP )
199         {
200                 // Set viewing volume info
201                 //glViewport(0,0,m_pageWidth/2,m_pageHeight/2); // Put this in to restrict area of page.
202
203                 GLfloat nRange = 100.0f;
204
205                 // Reset projection matrix stack
206                 glMatrixMode(GL_PROJECTION);
207                 glLoadIdentity();
208
209                 // Establish clipping volume (left, right, bottom, top, near, far)
210                 // This keeps the perspective square regardless of window or page size
211
212                 if (m_pageHeight <= m_pageWidth) 
213                 {
214                         glOrtho (-nRange, nRange, -nRange*m_pageHeight/m_pageWidth, nRange*m_pageHeight/m_pageWidth, -nRange, nRange);
215                 }
216                 else 
217                 {
218                         glOrtho (-nRange*m_pageWidth/m_pageHeight, nRange*m_pageWidth/m_pageHeight, -nRange, nRange, -nRange, nRange);
219                 }
220
221                 // Reset Model view matrix stack
222                 glMatrixMode(GL_MODELVIEW);
223                 glLoadIdentity();
224                 glRotatef(270.0f, 1.0, 0.0, 0.0);
225         }
226
227         return true;
228 }
229
230 inline void CGlPrinter::End( GLubyte *bm )
231 {
232         if ( m_printDLG.hDC )
233         {
234                 glFinish();
235
236                 if ( m_printMode == RENDER_TO_PRINTER )
237                 {
238                         if ( m_printerHGLRC )
239                         {
240                                 wglDeleteContext( m_printerHGLRC );
241                         }
242                 }
243                 else
244                 {
245                         if ( m_printMode == RENDER_TO_BITMAP )
246                         {
247                                 BitBlt( m_printDLG.hDC, 0,0, m_pageWidth,m_pageHeight, m_bitmapDC, 0,0, SRCCOPY );
248                         }
249                         else
250                         {
251                                 if ( m_printMode == READ_BITMAP )
252                                 {
253                                         glPixelStorei( GL_PACK_ALIGNMENT, 4 );
254                                         glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
255                                         glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
256                                         glPixelStorei( GL_PACK_SKIP_PIXELS, 0 );
257                                         //GLubyte *tempbitmap = (GLubyte *) malloc(m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*4);
258                                         glReadPixels( 0,0, m_bitmapInfo.bmiHeader.biWidth,m_bitmapInfo.bmiHeader.biHeight,
259                                                 GL_RGB, GL_UNSIGNED_BYTE, m_bitmap );
260                                 }
261                                 else
262                                 {
263                                         //PRINT_BITMAP
264                                         memcpy( m_bitmap, bm, m_bitmapInfo.bmiHeader.biSizeImage );
265                                 }
266                                 int i,j;
267                                 GLubyte *rgb, temp;
268                                 for ( i = 0; i < m_bitmapInfo.bmiHeader.biHeight; i++ )
269                                 {
270                                         for ( j = 0, rgb = ((GLubyte *)m_bitmap) + i * m_bitmapInfo.bmiHeader.biWidth * 3;
271                                         j < m_bitmapInfo.bmiHeader.biWidth;
272                                         j++, rgb +=3 )
273                                         {
274                                                 temp = rgb[0];
275                                                 rgb[0] = rgb[2];
276                                                 rgb[2] = temp;
277                                         }
278                                 }
279                                 long width = m_pageWidth;
280                                 long height = width * m_bitmapInfo.bmiHeader.biHeight / m_bitmapInfo.bmiHeader.biWidth;
281                                 if ( height > m_pageHeight )
282                                 {
283                                         height = m_pageHeight;
284                                         width = height * m_bitmapInfo.bmiHeader.biWidth / m_bitmapInfo.bmiHeader.biHeight;
285                                 }
286                                 long xoffset = (m_pageWidth - width) / 2;
287                                 long yoffset = (m_pageHeight - height) / 2;
288                                 StretchBlt( m_printDLG.hDC, xoffset, yoffset, width, height, m_bitmapDC, 0, 0,
289                                         m_bitmapInfo.bmiHeader.biWidth, m_bitmapInfo.bmiHeader.biHeight, SRCCOPY );
290                         }
291                         if ( m_bitmapDC ) 
292                         {
293                                 DeleteDC( m_bitmapDC );
294                         }
295                         if ( bitmapHandle )
296                         {
297                                 DeleteObject( bitmapHandle );
298                         }
299                         if ( m_bitmapHGLRC )
300                         {
301                                 wglDeleteContext( m_bitmapHGLRC );
302                         }
303                 }
304
305                 /* EndPage... */
306                 if ( EndPage( m_printDLG.hDC ) <=0 )
307                 {
308                         printf( "EndPage() failed\n" );
309                 }
310
311                 /* EndDoc... */
312                 if ( EndDoc( m_printDLG.hDC ) <=0 )
313                 {
314                         printf( "EndDoc() failed\n" );
315                 }
316
317                 // Delete the printer context when done with it
318                 DeleteDC(m_printDLG.hDC);
319                 
320                 // Restore window rendering context
321                 //wglMakeCurrent(hDC, hRC);
322                 wglMakeCurrent( NULL, NULL );
323
324         }
325 }