5 typedef enum { RENDER_TO_PRINTER, RENDER_TO_BITMAP, READ_BITMAP, PRINT_BITMAP } PRINTMODE;
7 inline CGlPrinter( PRINTMODE mode = READ_BITMAP );
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();
16 PRINTMODE m_printMode;
18 BITMAPINFO m_bitmapInfo;
24 int m_pageWidth; // Dimension of printer page (x)
25 int m_pageHeight; // Dimension of printer page (y)
28 inline double CGlPrinter::GetAspect()
30 return (double)m_pageWidth/(double)m_pageHeight;
33 inline int CGlPrinter::GetHorzRes()
38 inline int CGlPrinter::GetVertRes()
43 inline CGlPrinter::CGlPrinter( PRINTMODE mode ) :
44 m_printerHGLRC( 0 ), m_bitmapHGLRC( 0 ), m_printMode( mode ), m_bitmap( NULL )
48 inline CGlPrinter::~CGlPrinter()
52 inline bool CGlPrinter::Begin( char *title, int w, int h )
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
74 DOCINFO docInfo; // Document Info
75 int nPixelFormat; // Pixel format requested
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;
85 // Display printer dialog
86 if(!PrintDlg(&m_printDLG))
88 printf( "PrintDlg() failed %lx\n", GetLastError() );
92 // Get the dimensions of the page
93 m_pageWidth = GetDeviceCaps(m_printDLG.hDC, HORZRES);
94 m_pageHeight = GetDeviceCaps(m_printDLG.hDC, VERTRES);
96 // Initialize DocInfo structure
97 docInfo.cbSize = sizeof(DOCINFO);
98 docInfo.lpszDocName = title;
99 docInfo.lpszOutput = NULL;
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)
107 // Delete the printer context
108 DeleteDC(m_printDLG.hDC);
110 printf( "ChoosePixelFormat() failed %lx\n", GetLastError() );
114 // Start the document and page
115 StartDoc(m_printDLG.hDC, &docInfo);
116 StartPage(m_printDLG.hDC);
118 // Set the pixel format for the device context, but watch for failure
119 if(!SetPixelFormat(m_printDLG.hDC, nPixelFormat, &pPrintfd))
121 // Delete the printer context
122 DeleteDC(m_printDLG.hDC);
124 printf( "SetPixelFormat() failed %lx\n", GetLastError() );
128 // Create the Rendering context and make it current
129 if ( m_printMode == RENDER_TO_PRINTER )
131 m_printerHGLRC = wglCreateContext(m_printDLG.hDC);
132 wglMakeCurrent(m_printDLG.hDC, m_printerHGLRC);
136 memset( &m_bitmapInfo, 0, sizeof(BITMAPINFO) );
137 m_bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
138 if ( m_printMode == READ_BITMAP )
141 glGetIntegerv( GL_VIEWPORT, vp );
142 m_bitmapInfo.bmiHeader.biWidth = vp[2];
143 m_bitmapInfo.bmiHeader.biHeight = (vp[3] + 3) & ~3;
147 if ( m_printMode == RENDER_TO_BITMAP )
149 m_bitmapInfo.bmiHeader.biWidth = m_pageWidth;
150 m_bitmapInfo.bmiHeader.biHeight = m_pageHeight;
155 m_bitmapInfo.bmiHeader.biWidth = w;
156 m_bitmapInfo.bmiHeader.biHeight = h;
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 )
171 DeleteDC(m_printDLG.hDC);
172 printf( "CreateCompatibleDC() failed %lx\n", GetLastError() );
175 if ( SelectObject( m_bitmapDC, bitmapHandle ) == NULL )
177 DeleteDC(m_printDLG.hDC);
178 DeleteDC(m_bitmapDC);
179 printf( "SelectObject() failed %lx\n", GetLastError() );
182 PIXELFORMATDESCRIPTOR pfd;
183 memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
185 pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
186 pfd.iPixelType = PFD_TYPE_RGBA ;
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 )
193 m_bitmapHGLRC = wglCreateContext( m_bitmapDC );
194 wglMakeCurrent( m_bitmapDC, m_bitmapHGLRC );
198 if ( m_printMode == RENDER_TO_PRINTER || m_printMode == RENDER_TO_BITMAP )
200 // Set viewing volume info
201 //glViewport(0,0,m_pageWidth/2,m_pageHeight/2); // Put this in to restrict area of page.
203 GLfloat nRange = 100.0f;
205 // Reset projection matrix stack
206 glMatrixMode(GL_PROJECTION);
209 // Establish clipping volume (left, right, bottom, top, near, far)
210 // This keeps the perspective square regardless of window or page size
212 if (m_pageHeight <= m_pageWidth)
214 glOrtho (-nRange, nRange, -nRange*m_pageHeight/m_pageWidth, nRange*m_pageHeight/m_pageWidth, -nRange, nRange);
218 glOrtho (-nRange*m_pageWidth/m_pageHeight, nRange*m_pageWidth/m_pageHeight, -nRange, nRange, -nRange, nRange);
221 // Reset Model view matrix stack
222 glMatrixMode(GL_MODELVIEW);
224 glRotatef(270.0f, 1.0, 0.0, 0.0);
230 inline void CGlPrinter::End( GLubyte *bm )
232 if ( m_printDLG.hDC )
236 if ( m_printMode == RENDER_TO_PRINTER )
238 if ( m_printerHGLRC )
240 wglDeleteContext( m_printerHGLRC );
245 if ( m_printMode == RENDER_TO_BITMAP )
247 BitBlt( m_printDLG.hDC, 0,0, m_pageWidth,m_pageHeight, m_bitmapDC, 0,0, SRCCOPY );
251 if ( m_printMode == READ_BITMAP )
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 );
264 memcpy( m_bitmap, bm, m_bitmapInfo.bmiHeader.biSizeImage );
268 for ( i = 0; i < m_bitmapInfo.bmiHeader.biHeight; i++ )
270 for ( j = 0, rgb = ((GLubyte *)m_bitmap) + i * m_bitmapInfo.bmiHeader.biWidth * 3;
271 j < m_bitmapInfo.bmiHeader.biWidth;
279 long width = m_pageWidth;
280 long height = width * m_bitmapInfo.bmiHeader.biHeight / m_bitmapInfo.bmiHeader.biWidth;
281 if ( height > m_pageHeight )
283 height = m_pageHeight;
284 width = height * m_bitmapInfo.bmiHeader.biWidth / m_bitmapInfo.bmiHeader.biHeight;
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 );
293 DeleteDC( m_bitmapDC );
297 DeleteObject( bitmapHandle );
301 wglDeleteContext( m_bitmapHGLRC );
306 if ( EndPage( m_printDLG.hDC ) <=0 )
308 printf( "EndPage() failed\n" );
312 if ( EndDoc( m_printDLG.hDC ) <=0 )
314 printf( "EndDoc() failed\n" );
317 // Delete the printer context when done with it
318 DeleteDC(m_printDLG.hDC);
320 // Restore window rendering context
321 //wglMakeCurrent(hDC, hRC);
322 wglMakeCurrent( NULL, NULL );