00001
00002 class CGlPrinter
00003 {
00004 public:
00005 typedef enum { RENDER_TO_PRINTER, RENDER_TO_BITMAP, READ_BITMAP, PRINT_BITMAP } PRINTMODE;
00006 public:
00007 inline CGlPrinter( PRINTMODE mode = READ_BITMAP );
00008 inline ~CGlPrinter();
00009 inline bool Begin( char *title, int w=0, int h=0 );
00010 inline void End( GLubyte *bm=NULL );
00011 inline double GetAspect();
00012 inline int GetHorzRes();
00013 inline int GetVertRes();
00014
00015 private:
00016 PRINTMODE m_printMode;
00017 PRINTDLG m_printDLG;
00018 BITMAPINFO m_bitmapInfo;
00019 void *m_bitmap;
00020 HBITMAP bitmapHandle;
00021 HDC m_bitmapDC;
00022 HGLRC m_printerHGLRC;
00023 HGLRC m_bitmapHGLRC;
00024 int m_pageWidth;
00025 int m_pageHeight;
00026 };
00027
00028 inline double CGlPrinter::GetAspect()
00029 {
00030 return (double)m_pageWidth/(double)m_pageHeight;
00031 }
00032
00033 inline int CGlPrinter::GetHorzRes()
00034 {
00035 return m_pageWidth;
00036 }
00037
00038 inline int CGlPrinter::GetVertRes()
00039 {
00040 return m_pageHeight;
00041 }
00042
00043 inline CGlPrinter::CGlPrinter( PRINTMODE mode ) :
00044 m_printerHGLRC( 0 ), m_bitmapHGLRC( 0 ), m_printMode( mode ), m_bitmap( NULL )
00045 {
00046 }
00047
00048 inline CGlPrinter::~CGlPrinter()
00049 {
00050 }
00051
00052 inline bool CGlPrinter::Begin( char *title, int w, int h )
00053 {
00054
00055 static PIXELFORMATDESCRIPTOR pPrintfd = {
00056 sizeof(PIXELFORMATDESCRIPTOR),
00057 1,
00058 PFD_DRAW_TO_WINDOW |
00059 PFD_SUPPORT_OPENGL |
00060 PFD_SUPPORT_GDI |
00061 PFD_DEPTH_DONTCARE,
00062 PFD_TYPE_RGBA,
00063 24,
00064 0,0,0,0,0,0,
00065 0,0,
00066 0,0,0,0,0,
00067 0,
00068 0,
00069 0,
00070 0,
00071 0,
00072 0,0,0 };
00073
00074 DOCINFO docInfo;
00075 int nPixelFormat;
00076
00077
00078 memset(&m_printDLG,0,sizeof(PRINTDLG));
00079 m_printDLG.lStructSize = sizeof(PRINTDLG);
00080 m_printDLG.hwndOwner = GetForegroundWindow();
00081 m_printDLG.hDevMode = NULL;
00082 m_printDLG.hDevNames = NULL;
00083 m_printDLG.Flags = PD_RETURNDC | PD_ALLPAGES;
00084
00085
00086 if(!PrintDlg(&m_printDLG))
00087 {
00088 printf( "PrintDlg() failed %lx\n", GetLastError() );
00089 return false;
00090 }
00091
00092
00093 m_pageWidth = GetDeviceCaps(m_printDLG.hDC, HORZRES);
00094 m_pageHeight = GetDeviceCaps(m_printDLG.hDC, VERTRES);
00095
00096
00097 docInfo.cbSize = sizeof(DOCINFO);
00098 docInfo.lpszDocName = title;
00099 docInfo.lpszOutput = NULL;
00100
00101
00102
00103 nPixelFormat = ChoosePixelFormat(m_printDLG.hDC, &pPrintfd);
00104
00105 if(nPixelFormat == 0)
00106 {
00107
00108 DeleteDC(m_printDLG.hDC);
00109
00110 printf( "ChoosePixelFormat() failed %lx\n", GetLastError() );
00111 return false;
00112 }
00113
00114
00115 StartDoc(m_printDLG.hDC, &docInfo);
00116 StartPage(m_printDLG.hDC);
00117
00118
00119 if(!SetPixelFormat(m_printDLG.hDC, nPixelFormat, &pPrintfd))
00120 {
00121
00122 DeleteDC(m_printDLG.hDC);
00123
00124 printf( "SetPixelFormat() failed %lx\n", GetLastError() );
00125 return false;
00126 }
00127
00128
00129 if ( m_printMode == RENDER_TO_PRINTER )
00130 {
00131 m_printerHGLRC = wglCreateContext(m_printDLG.hDC);
00132 wglMakeCurrent(m_printDLG.hDC, m_printerHGLRC);
00133 }
00134 else
00135 {
00136 memset( &m_bitmapInfo, 0, sizeof(BITMAPINFO) );
00137 m_bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
00138 if ( m_printMode == READ_BITMAP )
00139 {
00140 GLint vp[4];
00141 glGetIntegerv( GL_VIEWPORT, vp );
00142 m_bitmapInfo.bmiHeader.biWidth = vp[2];
00143 m_bitmapInfo.bmiHeader.biHeight = (vp[3] + 3) & ~3;
00144 }
00145 else
00146 {
00147 if ( m_printMode == RENDER_TO_BITMAP )
00148 {
00149 m_bitmapInfo.bmiHeader.biWidth = m_pageWidth;
00150 m_bitmapInfo.bmiHeader.biHeight = m_pageHeight;
00151 }
00152 else
00153 {
00154
00155 m_bitmapInfo.bmiHeader.biWidth = w;
00156 m_bitmapInfo.bmiHeader.biHeight = h;
00157 }
00158 }
00159 m_bitmapInfo.bmiHeader.biPlanes = 1;
00160 m_bitmapInfo.bmiHeader.biBitCount = 24;
00161 m_bitmapInfo.bmiHeader.biCompression = BI_RGB;
00162 m_bitmapInfo.bmiHeader.biSizeImage = m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*3;
00163 m_bitmapInfo.bmiHeader.biXPelsPerMeter = 2952;
00164 m_bitmapInfo.bmiHeader.biYPelsPerMeter = 2952;
00165 m_bitmapInfo.bmiHeader.biClrUsed = 0;
00166 m_bitmapInfo.bmiHeader.biClrImportant = 0;
00167 bitmapHandle = CreateDIBSection( NULL, &m_bitmapInfo, DIB_RGB_COLORS, &m_bitmap, NULL, 0);
00168 m_bitmapDC = CreateCompatibleDC( NULL );
00169 if ( m_bitmapDC == NULL )
00170 {
00171 DeleteDC(m_printDLG.hDC);
00172 printf( "CreateCompatibleDC() failed %lx\n", GetLastError() );
00173 return false;
00174 }
00175 if ( SelectObject( m_bitmapDC, bitmapHandle ) == NULL )
00176 {
00177 DeleteDC(m_printDLG.hDC);
00178 DeleteDC(m_bitmapDC);
00179 printf( "SelectObject() failed %lx\n", GetLastError() );
00180 return false;
00181 }
00182 PIXELFORMATDESCRIPTOR pfd;
00183 memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
00184 pfd.nVersion = 1 ;
00185 pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
00186 pfd.iPixelType = PFD_TYPE_RGBA ;
00187 pfd.cColorBits = 24;
00188 pfd.iLayerType = PFD_MAIN_PLANE;
00189 int pixelFormat = ::ChoosePixelFormat(m_bitmapDC, &pfd);
00190 SetPixelFormat (m_bitmapDC, pixelFormat, &pfd);
00191 if ( m_printMode == RENDER_TO_BITMAP )
00192 {
00193 m_bitmapHGLRC = wglCreateContext( m_bitmapDC );
00194 wglMakeCurrent( m_bitmapDC, m_bitmapHGLRC );
00195 }
00196 }
00197
00198 if ( m_printMode == RENDER_TO_PRINTER || m_printMode == RENDER_TO_BITMAP )
00199 {
00200
00201
00202
00203 GLfloat nRange = 100.0f;
00204
00205
00206 glMatrixMode(GL_PROJECTION);
00207 glLoadIdentity();
00208
00209
00210
00211
00212 if (m_pageHeight <= m_pageWidth)
00213 {
00214 glOrtho (-nRange, nRange, -nRange*m_pageHeight/m_pageWidth, nRange*m_pageHeight/m_pageWidth, -nRange, nRange);
00215 }
00216 else
00217 {
00218 glOrtho (-nRange*m_pageWidth/m_pageHeight, nRange*m_pageWidth/m_pageHeight, -nRange, nRange, -nRange, nRange);
00219 }
00220
00221
00222 glMatrixMode(GL_MODELVIEW);
00223 glLoadIdentity();
00224 glRotatef(270.0f, 1.0, 0.0, 0.0);
00225 }
00226
00227 return true;
00228 }
00229
00230 inline void CGlPrinter::End( GLubyte *bm )
00231 {
00232 if ( m_printDLG.hDC )
00233 {
00234 glFinish();
00235
00236 if ( m_printMode == RENDER_TO_PRINTER )
00237 {
00238 if ( m_printerHGLRC )
00239 {
00240 wglDeleteContext( m_printerHGLRC );
00241 }
00242 }
00243 else
00244 {
00245 if ( m_printMode == RENDER_TO_BITMAP )
00246 {
00247 BitBlt( m_printDLG.hDC, 0,0, m_pageWidth,m_pageHeight, m_bitmapDC, 0,0, SRCCOPY );
00248 }
00249 else
00250 {
00251 if ( m_printMode == READ_BITMAP )
00252 {
00253 glPixelStorei( GL_PACK_ALIGNMENT, 4 );
00254 glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
00255 glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
00256 glPixelStorei( GL_PACK_SKIP_PIXELS, 0 );
00257
00258 glReadPixels( 0,0, m_bitmapInfo.bmiHeader.biWidth,m_bitmapInfo.bmiHeader.biHeight,
00259 GL_RGB, GL_UNSIGNED_BYTE, m_bitmap );
00260 }
00261 else
00262 {
00263
00264 memcpy( m_bitmap, bm, m_bitmapInfo.bmiHeader.biSizeImage );
00265 }
00266 int i,j;
00267 GLubyte *rgb, temp;
00268 for ( i = 0; i < m_bitmapInfo.bmiHeader.biHeight; i++ )
00269 {
00270 for ( j = 0, rgb = ((GLubyte *)m_bitmap) + i * m_bitmapInfo.bmiHeader.biWidth * 3;
00271 j < m_bitmapInfo.bmiHeader.biWidth;
00272 j++, rgb +=3 )
00273 {
00274 temp = rgb[0];
00275 rgb[0] = rgb[2];
00276 rgb[2] = temp;
00277 }
00278 }
00279 long width = m_pageWidth;
00280 long height = width * m_bitmapInfo.bmiHeader.biHeight / m_bitmapInfo.bmiHeader.biWidth;
00281 if ( height > m_pageHeight )
00282 {
00283 height = m_pageHeight;
00284 width = height * m_bitmapInfo.bmiHeader.biWidth / m_bitmapInfo.bmiHeader.biHeight;
00285 }
00286 long xoffset = (m_pageWidth - width) / 2;
00287 long yoffset = (m_pageHeight - height) / 2;
00288 StretchBlt( m_printDLG.hDC, xoffset, yoffset, width, height, m_bitmapDC, 0, 0,
00289 m_bitmapInfo.bmiHeader.biWidth, m_bitmapInfo.bmiHeader.biHeight, SRCCOPY );
00290 }
00291 if ( m_bitmapDC )
00292 {
00293 DeleteDC( m_bitmapDC );
00294 }
00295 if ( bitmapHandle )
00296 {
00297 DeleteObject( bitmapHandle );
00298 }
00299 if ( m_bitmapHGLRC )
00300 {
00301 wglDeleteContext( m_bitmapHGLRC );
00302 }
00303 }
00304
00305
00306 if ( EndPage( m_printDLG.hDC ) <=0 )
00307 {
00308 printf( "EndPage() failed\n" );
00309 }
00310
00311
00312 if ( EndDoc( m_printDLG.hDC ) <=0 )
00313 {
00314 printf( "EndDoc() failed\n" );
00315 }
00316
00317
00318 DeleteDC(m_printDLG.hDC);
00319
00320
00321
00322 wglMakeCurrent( NULL, NULL );
00323
00324 }
00325 }