1 // File: GLViewer_Widget.cxx
2 // Created: November, 2004
4 // Copyright (C) CEA 2004
6 /***************************************************************************
7 ** Class: GLViewer_Widget
8 ** Descr: OpenGL QWidget for GLViewer
10 ** Created: UI team, 27.03.03
11 ****************************************************************************/
13 #include "GLViewer_Widget.h"
15 #include "GLViewer_ViewPort2d.h"
16 #include "GLViewer_Viewer2d.h"
17 #include "GLViewer_Object.h"
19 //#include "QAD_Application.h"
20 //#include <QAD_Desktop.h>
26 //#include <iostream.h>
33 #include <qapplication.h>
35 #include <qpaintdevicemetrics.h>
40 #include <qfontdialog.h>
41 #include <qfontmetrics.h>
45 static GLuint texFont;
53 QFont aFont = QFontDialog::getFont( &ok/*, QAD_Application::getDesktop()*/ );
54 QFontMetrics aFM( aFont );
56 for( int k = 32; k <= 127; k++ )
58 char aLetter = (char)k;
62 int pixelsWidth = aFM.width( aStr );
63 int pixelsHigh = aFM.height();
67 while( aFontX < pixelsWidth )
69 while( aFontY < pixelsHigh )
72 QPixmap* aPixmap = new QPixmap( aFontX, aFontY );
73 aPixmap->fill( QColor( 255, 255, 255) );
74 QPainter aPainter( aPixmap );
75 aPainter.setFont( aFont );
76 aPainter.drawText ( 0, pixelsHigh, aStr );
77 QImage aImage = aPixmap->convertToImage();
79 aImage.save( "W:\\Temp\\pic.jpg", "JPEG" );
81 char* pixels = new char[aFontX * aFontY * 2];
83 for( int i = 0; i < aFontY; i++ )
85 for( int j = 0; j < aFontX; j++ )
87 if( qRed( aImage.pixel( j, aFontY - i - 1 ) ) == 0 )
89 pixels[i * aFontX * 2 + j * 2] = (char) 255;
90 pixels[i * aFontX * 2 + j * 2 + 1]= (char) 255;
94 pixels[i * aFontX * 2 + j * 2] = (char) 0;
95 pixels[i * aFontX * 2 + j * 2 + 1]= (char) 0;
100 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
101 glGenTextures(1, &texFont);
102 glBindTexture(GL_TEXTURE_2D, texFont);
103 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
104 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
105 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
107 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
108 glTexImage2D(GL_TEXTURE_2D, 0, 2, aFontX,
109 aFontY, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
117 static void showFont()
119 glEnable(GL_TEXTURE_2D);
120 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
121 glAlphaFunc(GL_GEQUAL, 0.005F);
122 glEnable(GL_ALPHA_TEST);
123 glColor3f( 1.0, 1.0, 1.0);
124 glBindTexture(GL_TEXTURE_2D, texFont);
127 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -fontW/2, -fontH/2, 1.0 );
128 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -fontW/2, fontH/2, 1.0 );
129 glTexCoord2f( 1.0, 1.0 ); glVertex3f( fontW/2, fontH/2, 1.0 );
130 glTexCoord2f( 1.0, 0.0 ); glVertex3f( fontW/2, -fontH/2, 1.0 );
134 glDisable(GL_ALPHA_TEST);
135 glDisable(GL_TEXTURE_2D);
139 GLViewer_Widget::GLViewer_Widget( QWidget* parent, const char* name ):
140 QGLWidget( parent, 0/*, WRepaintNoErase | WResizeNoErase*/ )
142 myViewPort = ( GLViewer_ViewPort2d* )parent;
150 myRotationAngle = 0.0;
151 myRotationCenterX = 0.0;
152 myRotationCenterY = 0.0;
153 myRotationCenterZ = 1.0;
154 myRotationAnglePrev = 0.0;
158 isExportMode = false;
161 setMouseTracking( true );
164 GLViewer_Widget::~GLViewer_Widget()
168 void GLViewer_Widget::getPan( GLfloat& xPan, GLfloat& yPan, GLfloat& zPan )
175 void GLViewer_Widget::setPan( GLfloat xPan, GLfloat yPan, GLfloat zPan )
182 void GLViewer_Widget::getScale( GLfloat& xScale, GLfloat& yScale, GLfloat& zScale )
189 void GLViewer_Widget::setScale( GLfloat xScale, GLfloat yScale, GLfloat zScale )
191 if ( xScale > 0 && yScale > 0 && zScale > 0 )
199 void GLViewer_Widget::getRotationStart( GLfloat& rotationStartX, GLfloat& rotationStartY,
200 GLfloat& rotationStartZ )
202 rotationStartX = myRotationStartX;
203 rotationStartY = myRotationStartY;
204 rotationStartZ = myRotationStartZ;
207 void GLViewer_Widget::setRotationStart( GLfloat rotationStartX, GLfloat rotationStartY,
208 GLfloat rotationStartZ )
210 myRotationStartX = rotationStartX;
211 myRotationStartY = rotationStartY;
212 myRotationStartZ = rotationStartZ;
215 void GLViewer_Widget::getRotation( GLfloat& rotationAngle, GLfloat& rotationCenterX,
216 GLfloat& rotationCenterY, GLfloat& rotationCenterZ )
218 rotationAngle = myRotationAngle;
219 rotationCenterX = myRotationCenterX;
220 rotationCenterY = myRotationCenterY;
221 rotationCenterZ = myRotationCenterZ;
224 void GLViewer_Widget::setRotation( GLfloat rotationAngle, GLfloat rotationCenterX,
225 GLfloat rotationCenterY, GLfloat rotationCenterZ )
227 myRotationAngle = rotationAngle;
228 myRotationCenterX = rotationCenterX;
229 myRotationCenterY = rotationCenterY;
230 myRotationCenterZ = rotationCenterZ;
233 void GLViewer_Widget::setBackground( QString filename )
238 if ( !filename.isEmpty() && buf.load( filename ) )
239 { // Load first image from file
240 isLoadBackground = true;
241 myBackgroundFile = filename;
246 myBackgroundSize = 64;
247 while( myBackgroundSize < myIW || myBackgroundSize < myIH)
248 myBackgroundSize = myBackgroundSize * 2;
250 GLubyte* pixels = new GLubyte[myBackgroundSize * myBackgroundSize * 4];
252 for( int i = 0; i < myBackgroundSize; i++ )
254 for( int j = 0; j < myBackgroundSize; j++ )
256 if( j < myIW && i < myIH )
258 pixels[i * myBackgroundSize * 4 + j * 4] = (GLubyte)qRed( buf.pixel(j,myIH - i - 1) );
259 pixels[i * myBackgroundSize * 4 + j * 4 + 1]= (GLubyte)qGreen( buf.pixel(j,myIH - i - 1) );
260 pixels[i * myBackgroundSize * 4 + j * 4 + 2] = (GLubyte)qBlue( buf.pixel(j,myIH - i - 1) );
264 pixels[i * myBackgroundSize * 4 + j * 4] = (GLubyte)0;
265 pixels[i * myBackgroundSize * 4 + j * 4 + 1] = (GLubyte)0;
266 pixels[i * myBackgroundSize * 4 + j * 4 + 2] = (GLubyte)0;
268 pixels[i * myBackgroundSize* 4 + j * 4 + 3] = (GLubyte)255;
273 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
274 glGenTextures(1, &texName);
275 glBindTexture(GL_TEXTURE_2D, texName);
276 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
277 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
280 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myBackgroundSize , myBackgroundSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
288 void GLViewer_Widget::addToolTip( QString theString, QRect theRect )
290 myToolTipRect = theRect;
291 QToolTip::add( this, myToolTipRect, theString );
294 void GLViewer_Widget::removeToolTip()
296 QToolTip::remove( this, myToolTipRect );
299 void GLViewer_Widget::initializeGL()
301 setAutoBufferSwap( true );
303 // cout << "GLViewer_Widget::initializeGL" << endl;
305 //glClearColor( 0.0, 0.0, 0.0, 0.0 );
307 glShadeModel(GL_FLAT);
311 QString aPicturePath = getenv("GLViewer__Background_Picture");
313 if ( !aPicturePath.isEmpty() && buf.load( aPicturePath ) )
314 { // Load first image from file
315 isLoadBackground = true;
316 setBackground( aPicturePath );
318 // for test texture font
322 QFont aFont = QFontDialog::getFont( &ok, this );
323 QFontMetrics aFM( aFont );
324 int pixelsWidth = aFM.width( "What's the width of this text?" );
325 int pixelsHigh = aFM.height();
329 while( aFontX < pixelsWidth )
331 while( aFontY < pixelsHigh )
337 QPixmap* aPixmap = new QPixmap( aFontX, aFontY );
338 aPixmap->fill( QColor( 255, 255, 255) );
339 QPainter aPainter( aPixmap );
340 aPainter.setFont( aFont );
341 //Painter.setPen( QColor( 0, 0, 0 ) );
342 aPainter.drawText ( 0, pixelsHigh, "A" );
343 QImage aImage = aPixmap->convertToImage();
345 aImage.save( "W:\\Temp\\pic.jpg", "JPEG" );
347 GLubyte* pixels = new GLubyte[aFontX * aFontY * 2];
349 for( int i = 0; i < aFontY; i++ )
351 for( int j = 0; j < aFontX; j++ )
353 if( qRed( aImage.pixel( j, myIH - i - 1 ) ) == 0 )
355 pixels[i * aFontX * 2 + j * 2] = (GLubyte) 255;
356 pixels[i * aFontX * 2 + j * 2 + 1]= (GLubyte) 255;
360 pixels[i * aFontX * 2 + j * 2] = (GLubyte) 0;
361 pixels[i * aFontX * 2 + j * 2 + 1]= (GLubyte) 0;
367 glBindTexture(GL_TEXTURE_2D, texName);
368 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
369 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
370 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
371 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
372 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
373 glTexImage2D(GL_TEXTURE_2D, 0, 2, aFontX,
374 aFontY, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
379 //tex2 = buf.convertDepth( 32, 0 );
381 //tex1 = QGLWidget::convertToGLFormat( tex2 ); // flipped 32bit RGBA
383 /*myIW = buf.width();
386 myBackgroundSize = 64;
387 while( myBackgroundSize < myIW || myBackgroundSize < myIH)
388 myBackgroundSize = myBackgroundSize * 2;
390 GLubyte* pixels = new GLubyte[myBackgroundSize * myBackgroundSize * 4];
392 //GLubyte pixels[512][512][3];
393 for( int i = 0; i < myBackgroundSize; i++ )
395 for( int j = 0; j < myBackgroundSize; j++ )
397 if( j < myIW && i < myIH )
399 pixels[i * myBackgroundSize * 4 + j * 4] = (GLubyte)qRed( buf.pixel(j,myIH - i - 1) );
400 pixels[i * myBackgroundSize * 4 + j * 4 + 1]= (GLubyte)qGreen( buf.pixel(j,myIH - i - 1) );
401 pixels[i * myBackgroundSize * 4 + j * 4 + 2] = (GLubyte)qBlue( buf.pixel(j,myIH - i - 1) );
405 pixels[i * myBackgroundSize * 4 + j * 4] = (GLubyte)0;
406 pixels[i * myBackgroundSize * 4 + j * 4 + 1] = (GLubyte)0;
407 pixels[i * myBackgroundSize * 4 + j * 4 + 2] = (GLubyte)0;
409 pixels[i * myBackgroundSize* 4 + j * 4 + 3] = (GLubyte)255;
410 //cout << "RED = " << qRed( buf.pixel(i,j) ) << " GREEN = " << qGreen( buf.pixel(i,j) ) <<
411 // " BLUE = " << qBlue( buf.pixel(i,j) ) << endl;
416 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
417 glGenTextures(1, &texName);
418 glBindTexture(GL_TEXTURE_2D, texName);
419 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
423 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myBackgroundSize , myBackgroundSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
432 isLoadBackground = false;
434 //GLViewer_TexFont aTexFont;
435 //aTexFont.generateTexture();
436 //aTexFont.drawString( "hello" );
440 void GLViewer_Widget::paintGL()
442 // cout << "GLViewer_Widget::paintGL" << endl;
444 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
446 glMatrixMode( GL_MODELVIEW );
449 glRotatef( myRotationAngle, myRotationCenterX, myRotationCenterY, myRotationCenterZ );
450 glScalef( myXScale, myYScale, myZScale );
451 glTranslatef( myXPan, myYPan, myZPan );
452 //glRotatef( myRotationAngle, myRotationCenterX, myRotationCenterY, myRotationCenterZ );
454 if( isLoadBackground )
456 glEnable(GL_TEXTURE_2D);
457 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
458 glBindTexture(GL_TEXTURE_2D, texName);
461 glTexCoord2f( 0.0, 0.0); glVertex3f( -myIW/2, -myIH/2, 0.0);
462 glTexCoord2f( 0.0, (float)myIH/myBackgroundSize ); glVertex3f( -myIW/2, myIH/2, 0.0);
463 glTexCoord2f( (float)myIW/myBackgroundSize, (float)myIH/myBackgroundSize ); glVertex3f( myIW/2, myIH/2, 0.0);
464 glTexCoord2f( (float)myIW/myBackgroundSize, 0.0); glVertex3f( myIW/2, -myIH/2, 0.0);
468 glDisable(GL_TEXTURE_2D);
470 // for test texture font
472 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
476 GLViewer_RectangularGrid* grid = myViewPort->getGrid();
479 //myViewPort->drawCompass();
481 //glEnable( GL_POLYGON_OFFSET_FILL );
482 //glPolygonOffset( 0, 1 );
484 GLViewer_Viewer2d* v = ( GLViewer_Viewer2d* )getViewPort()->getViewFrame()->getViewer();
486 v->updateDrawers( GL_FALSE, myXScale, myYScale );
488 v->repaintView( getViewPort()->getViewFrame() );
490 //glDisable( GL_POLYGON_OFFSET_FILL );
492 // GLViewer_TexFont aTexFont;
493 // aTexFont.generateTexture();
494 // aTexFont.drawString( "hello" );
497 void GLViewer_Widget::resizeGL( int w, int h )
499 // cout << "GLViewer_Widget::resizeGL " << w << " " << h << endl;
503 glViewport( 0, 0, w, h);
512 myViewPort->initResize( w, h );
514 GLViewer_Viewer2d* v = ( GLViewer_Viewer2d* )getViewPort()->getViewFrame()->getViewer();
515 v->updateDrawers( GL_FALSE, myXScale, myYScale );
517 glMatrixMode( GL_PROJECTION );
519 GLfloat w_c = w / 2., h_c = h / 2.;
521 gluOrtho2D( -w_c, w_c, -h_c, h_c );
523 glMatrixMode( GL_MODELVIEW );
527 void GLViewer_Widget::copyBuffers()
529 // cout << "GLViewer_Widget::copyBuffers" << endl;
532 glGetIntegerv( GL_VIEWPORT, val );
533 glReadBuffer( GL_FRONT );
534 glCopyPixels( val[0], val[1], val[2], val[3], GL_COLOR );
537 void GLViewer_Widget::exportRepaint()
543 isExportMode = false;
547 void GLViewer_Widget::paintEvent( QPaintEvent* e )
549 // cout << "GLViewer_Widget::paintEvent" << endl;
550 QApplication::sendEvent( myViewPort, e );
553 void GLViewer_Widget::mouseMoveEvent( QMouseEvent* e )
555 // cout << "GLViewer_Widget::mouseMoveEvent" << endl;
556 QApplication::sendEvent( myViewPort, e );
559 void GLViewer_Widget::mousePressEvent( QMouseEvent* e )
561 // cout << "GLViewer_Widget::mousePressEvent" << endl;
562 QApplication::sendEvent( myViewPort, e );
565 void GLViewer_Widget::mouseReleaseEvent( QMouseEvent* e )
567 // cout << "GLViewer_Widget::mouseReleaseEvent" << endl;
568 QApplication::sendEvent( myViewPort, e );
571 void GLViewer_Widget::enterEvent( QEvent* e )
573 // cout << "GLViewer_Widget::enterEvent" << endl;
576 void GLViewer_Widget::leaveEvent( QEvent* e )
578 // cout << "GLViewer_Widget::leaveEvent" << endl;
582 inline char hex( uchar c )
590 void AddImagePart( QFile& hFile, QImage& image, int w1, int w2, int h1, int h2,
591 GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS,
592 double a, double b, double c, double d, double dw, double dh )
594 if( aViewerCS && aPSCS )
596 double width = w2-w1+1, height = h2-h1+1;
597 QString aBuffer = "", temp = "%1 %2 8 [ %3 %4 %5 %6 %7 %8 ]\n";
598 aBuffer += temp.arg( width ).arg( height ).
599 arg( a ).arg( b ).arg( c ).arg( d ).
603 char line[81]; line[80] = '\0'; int cur_index = 0;
605 for( int i=h2; i>=h1; i-- )
607 uchar* theCurLine = image.scanLine( i ), cur;
608 for( int j=w1; j<=w2; j++ )
609 for( int k=0; k<3; k++ )
611 cur = *(theCurLine+4*j+2-k);
612 *(line+cur_index) = hex( cur/16 ); //HI
613 *(line+cur_index+1) = hex( cur%16 ); //LO
625 aBuffer += "> false 3 colorimage\n\n";
627 hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
631 void GLViewer_Widget::getBackgroundRectInViewerCS( double& left, double& top, double& right, double& bottom )
633 left = -myIW/2; right = myIW/2;
634 top = myIH/2; bottom = -myIH/2;
637 void GLViewer_Widget::translateBackgroundToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
641 if( aViewerCS && aPSCS && isLoadBackground && buf.load( myBackgroundFile ) )
643 double a, b, c, d, dx, dy; //The preparation of transformation matrix
645 double width = buf.width(), height = buf.height();
647 double left, top, right, bottom;
648 getBackgroundRectInViewerCS( left, top, right, bottom );
650 double aax = left, aay = bottom,
651 bbx = right, bby = bottom,
652 ccx = left, ccy = top;
654 aViewerCS->transform( *aPSCS, aax, aay );
655 aViewerCS->transform( *aPSCS, bbx, bby );
656 aViewerCS->transform( *aPSCS, ccx, ccy );
658 a = ( bbx - aax ) / width;
659 b = ( ccx - aax ) / height;
660 c = ( bby - aay ) / width;
661 d = ( ccy - aay ) / height;
663 //Now we must find invert matrix
664 double det = a*d-b*c,
670 a = newa; b = newb; c = newc; d = newd;
673 dy = -(b*aax+d*aay); //according to PS specification of coordinate transformation
675 const int max = 133000; //The maximum length of string in PS
676 int dh = int( floor( double( max ) / ( 3.0*2.0*width ) ) );
677 for( int k=buf.height()-1; k>=0; k-=dh )
678 AddImagePart( hFile, buf, 0, buf.width()-1, QMAX( k-dh+1, 0 ), k,
679 aViewerCS, aPSCS, a, b, c, d, dx, dy-(buf.height()-1-k) );
683 void DecodeScanLine( int width, uchar* dest, int dest_depth, uchar* source, int source_depth )
686 typedef unsigned int WORD;
689 int aSize = width*dest_depth,
695 if( dest_depth==source_depth )
696 memcpy( dest, source, aSize/8 );
699 double r, g, b; WORD color;
700 for( int i=0; i<width; i++ )
703 switch( source_depth )
706 memcpy( &color, source + 2*i, 2 );
707 b = double( color & 0x001F ) / 31.0;
708 g = double( ( color & 0x07E0 ) >> 5 ) / 63.0;
709 r = double( ( color & 0xF800 ) >> 11 ) / 31.0;
712 b = double( *(source + 3*i) ) / 255.0;
713 g = double( *(source + 3*i+1) ) / 255.0;
714 r = double( *(source + 3*i+2) ) / 255.0;
717 b = double( *(source + 4*i) ) / 255.0;
718 g = double( *(source + 4*i+1) ) / 255.0;
719 r = double( *(source + 4*i+2) ) / 255.0;
725 color = WORD(b*31.0);
726 color += (WORD(g*63.0)<<5);
727 color += (WORD(r*31.0)<<11);
728 memcpy( dest + 2*i, &color, 2 );
731 *( dest + 3*i ) = 255*b;
732 *( dest + 3*i+1 ) = 255*g;
733 *( dest + 3*i+2 ) = 255*r;
736 *( dest + 4*i ) = 255*b;
737 *( dest + 4*i+1 ) = 255*g;
738 *( dest + 4*i+2 ) = 255*r;
739 *( dest + 4*i+3 ) = 0;
747 void GLViewer_Widget::translateBackgroundToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
751 if( aViewerCS && aEMFCS && isLoadBackground && buf.load( myBackgroundFile ) )
753 double left, top, right, bottom;
754 getBackgroundRectInViewerCS( left, top, right, bottom );
756 double aRot = aViewerCS->getRotation();
758 double lx = left, ly = top;
759 aViewerCS->transform( *aEMFCS, lx, ly );
761 aViewerCS->setRotation( 0.0 ); //we switch off the rotation of CS
763 aViewerCS->transform( *aEMFCS, left, top );
764 aViewerCS->transform( *aEMFCS, right, bottom );
769 HDC aScrDC = GetDC( 0 );
770 HDC aCompDC = CreateCompatibleDC( aScrDC );
771 HBITMAP aBMP = CreateCompatibleBitmap( aScrDC, w, h );
774 GetObject ( aBMP, sizeof(BITMAP), &aBitInfo );
775 int depth = aBitInfo.bmBitsPixel; //how many bits represent a color of one pixel
777 int aLineSize = w*depth;
778 int dw = aLineSize % 32; //scanline word aligning
785 BYTE* bits = new BYTE[aLineSize*h];
786 memset( bits, 0, aLineSize*h );
789 for( int i=0; i<h; i++ )
791 aLine = buf.scanLine( i );
792 DecodeScanLine( w, bits+aLineSize*i, depth, aLine, buf.depth() );
795 SetBitmapBits( aBMP, aLineSize*h, bits );
797 HGDIOBJ old = SelectObject( aCompDC, aBMP );
800 GetWorldTransform( dc, &aTrans );
801 XFORM aRotTrans = aTrans;
802 double a = aRotTrans.eM11,
807 aRotTrans.eM11 = a*cos( aRot )-b*sin( aRot ); //we multiply the current matrix with the rotation matrix
808 aRotTrans.eM12 = a*sin( aRot )+b*cos( aRot );
809 aRotTrans.eM21 = c*cos( aRot )-d*sin( aRot );
810 aRotTrans.eM22 = c*sin( aRot )+d*cos( aRot );
817 double det = a*d-b*c, //now we find the invert matrix
823 a = newa; b = newb; c = newc; d = newd;
825 aRotTrans.eDx = lx -(a*left+c*top); //we find the dx and dy translating (left,top)->(lx,ly) -
826 aRotTrans.eDy = ly -(b*left+d*top); //the real image of left-top corner of picture
828 SetWorldTransform( dc, &aRotTrans );
829 int res = StretchBlt( dc, left, top, right-left, bottom-top, aCompDC, 0, 0, w, h, SRCCOPY );
830 SetWorldTransform( dc, &aTrans );
832 SelectObject( aCompDC, old );
834 ReleaseDC( 0, aScrDC );
836 DeleteObject( aBMP );
839 aViewerCS->setRotation( aRot );