lib Library API Documentation

kowmfreadprivate.cc

00001 /* This file is part of the KDE libraries
00002  * Copyright (c) 1998 Stefan Taferner
00003  *                    2001/2003 thierry lorthiois (lorthioist@wanadoo.fr)
00004  * With the help of WMF documentation by Caolan Mc Namara
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License version 2 as published by the Free Software Foundation.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <math.h>
00022 #include <qfileinfo.h>
00023 #include <qimage.h>
00024 #include <qwmatrix.h>
00025 #include <qptrlist.h>
00026 #include <qpointarray.h>
00027 #include <qdatastream.h>
00028 #include <kdebug.h>
00029 
00030 #include "kowmfreadprivate.h"
00031 #include "kowmfread.h"
00032 
00033 
00034 KoWmfReadPrivate::KoWmfReadPrivate()
00035 {
00036     mNbrFunc = 0;
00037     mValid = false;
00038     mStandard = false;
00039     mPlaceable = false;
00040     mEnhanced = false;
00041     mBuffer = 0;
00042     mObjHandleTab = 0;
00043 }
00044 
00045 
00046 KoWmfReadPrivate::~KoWmfReadPrivate()
00047 {
00048     if ( mObjHandleTab != 0 ) {
00049         for ( int i=0 ; i < mNbrObject ; i++ ) {
00050             if ( mObjHandleTab[i] != 0 )
00051                 delete mObjHandleTab[i];
00052         }
00053         delete[] mObjHandleTab;
00054     }
00055     if ( mBuffer != 0 ) {
00056         mBuffer->close();
00057         delete mBuffer;
00058     }
00059 }
00060 
00061 
00062 bool KoWmfReadPrivate::load( const QByteArray& array )
00063 {
00064     // delete previous buffer
00065     if ( mBuffer != 0 ) {
00066         mBuffer->close();
00067         delete mBuffer;
00068     }
00069 
00070     // load into buffer
00071     mBuffer = new QBuffer( array );
00072     mBuffer->open( IO_ReadOnly );
00073 
00074     // read and check the header
00075     WmfEnhMetaHeader eheader;
00076     WmfMetaHeader header;
00077     WmfPlaceableHeader pheader;
00078     unsigned short checksum;
00079     int filePos;
00080 
00081     QDataStream st( mBuffer );
00082     st.setByteOrder( QDataStream::LittleEndian );
00083     mStackOverflow = mWinding = false;
00084     mTextAlign = mTextRotation = 0;
00085     mTextColor = Qt::black;
00086     mValid = false;
00087     mStandard = false;
00088     mPlaceable = false;
00089     mEnhanced = false;
00090 
00091     //----- Read placeable metafile header
00092     st >> pheader.key;
00093     if ( pheader.key==( Q_UINT32 )APMHEADER_KEY ) {
00094         mPlaceable = true;
00095         st >> pheader.handle;
00096         st >> pheader.left;
00097         st >> pheader.top;
00098         st >> pheader.right;
00099         st >> pheader.bottom;
00100         st >> pheader.inch;
00101         st >> pheader.reserved;
00102         st >> pheader.checksum;
00103         checksum = calcCheckSum( &pheader );
00104         if ( pheader.checksum!=checksum ) {
00105             return false;  
00106         }
00107         st >> header.fileType;
00108         st >> header.headerSize;
00109         st >> header.version;
00110         st >> header.fileSize;
00111         st >> header.numOfObjects;
00112         st >> header.maxRecordSize;
00113         st >> header.numOfParameters;
00114         mNbrObject = header.numOfObjects;
00115         mBBox.setLeft( pheader.left );
00116         mBBox.setTop( pheader.top );
00117         mBBox.setRight( pheader.right );
00118         mBBox.setBottom( pheader.bottom );
00119         mDpi = pheader.inch;
00120     }
00121     else {
00122         mBuffer->at( 0 );
00123         //----- Read as enhanced metafile header
00124         filePos = mBuffer->at();
00125         st >> eheader.recordType;
00126         st >> eheader.recordSize;
00127         st >> eheader.boundsLeft;
00128         st >> eheader.boundsTop;
00129         st >> eheader.boundsRight;
00130         st >> eheader.boundsBottom;
00131         st >> eheader.frameLeft;
00132         st >> eheader.frameTop;
00133         st >> eheader.frameRight;
00134         st >> eheader.frameBottom;
00135         st >> eheader.signature;
00136         if ( eheader.signature==ENHMETA_SIGNATURE ) {
00137             mEnhanced = true;
00138             st >> eheader.version;
00139             st >> eheader.size;
00140             st >> eheader.numOfRecords;
00141             st >> eheader.numHandles;
00142             st >> eheader.reserved;
00143             st >> eheader.sizeOfDescription;
00144             st >> eheader.offsetOfDescription;
00145             st >> eheader.numPaletteEntries;
00146             st >> eheader.widthDevicePixels;
00147             st >> eheader.heightDevicePixels;
00148             st >> eheader.widthDeviceMM;
00149             st >> eheader.heightDeviceMM;
00150         }
00151         else {
00152             //----- Read as standard metafile header
00153             mStandard = true;
00154             mBuffer->at( filePos );
00155             st >> header.fileType;
00156             st >> header.headerSize;
00157             st >> header.version;
00158             st >> header.fileSize;
00159             st >> header.numOfObjects;
00160             st >> header.maxRecordSize;
00161             st >> header.numOfParameters;
00162             mNbrObject = header.numOfObjects;
00163         }
00164     }
00165     mOffsetFirstRecord = mBuffer->at();
00166 
00167     //----- Test header validity
00168     if ( ((header.headerSize == 9) && (header.numOfParameters == 0)) || (mPlaceable) ) {
00169         // valid wmf file
00170         mValid = true;
00171     }
00172     else {
00173         kdDebug() << "KoWmfReadPrivate : incorrect file format !" << endl;
00174     }
00175 
00176     // check bounding rectangle for standard meta file
00177     if ( (mValid) && (mStandard) ) {
00178         Q_UINT16 numFunction = 1;
00179         Q_UINT32 size;
00180         bool firstOrg=true, firstExt=true;
00181 
00182         // search functions setWindowOrg and setWindowExt
00183         while ( numFunction ) {
00184             filePos = mBuffer->at();
00185             st >> size >> numFunction;
00186 
00187             if ( size == 0 ) {
00188                 kdDebug() << "KoWmfReadPrivate : incorrect file!" << endl;
00189                 mValid = 0;
00190                 break;
00191             }
00192 
00193             numFunction &= 0xFF;
00194             if ( numFunction == 11 ) {
00195                 Q_INT16 top, left;
00196 
00197                 st >> top >> left;
00198                 if ( firstOrg ) {
00199                     firstOrg = false;
00200                     mBBox.setLeft( left );
00201                     mBBox.setTop( top );
00202                 }
00203                 else {
00204                     if ( left < mBBox.left() ) mBBox.setLeft( left );
00205                     if ( top < mBBox.top() ) mBBox.setTop( top );
00206                 }
00207             }
00208             if ( numFunction == 12 ) {
00209                 Q_INT16 width, height;
00210 
00211                 st >> height >> width;
00212                 if ( width < 0 ) width = -width;
00213                 if ( height < 0 ) height = -height;
00214                 if ( firstExt ) {
00215                     firstExt = false;
00216                     mBBox.setWidth( width );
00217                     mBBox.setHeight( height );
00218                 }
00219                 else {
00220                     if ( width > mBBox.width() ) mBBox.setWidth( width );
00221                     if ( height > mBBox.height() ) mBBox.setHeight( height );
00222                 }
00223             }
00224             mBuffer->at( filePos + (size<<1) );
00225             // ## shouldn't we break from the loop as soon as we found what we were looking for?
00226         }
00227     }
00228 
00229     return (mValid);
00230 }
00231 
00232 
00233 bool KoWmfReadPrivate::play( KoWmfRead* readWmf )
00234 {
00235     if ( !(mValid) ) {
00236         kdDebug() << "KoWmfReadPrivate::play : invalid WMF file" << endl;
00237         return false;
00238     }
00239 
00240     if ( mNbrFunc ) {
00241         if ( (mStandard) ) {
00242             kdDebug() << "Standard : " << mBBox.left() << "  "  << mBBox.top() << "  "  << mBBox.width() << "  "  << mBBox.height() << endl;
00243         }
00244         else {
00245             kdDebug() << "DPI : " << mDpi << " : " << mBBox.left() << "  "  << mBBox.top() << "  "  << mBBox.width() << "  "  << mBBox.height() << endl;
00246             kdDebug() << "inch : " << mBBox.width()/mDpi << "  " << mBBox.height()/mDpi << endl;
00247             kdDebug() << "mm : " << mBBox.width()*25.4/mDpi << "  " << mBBox.height()*25.4/mDpi << endl;
00248         }
00249         kdDebug() << mValid << "  " << mStandard << "  " << mPlaceable << endl;
00250     }
00251 
00252     // stack of handle
00253     mObjHandleTab = new KoWmfHandle* [ mNbrObject ];
00254     for ( int i=0; i < mNbrObject ; i++ ) {
00255         mObjHandleTab[ i ] = 0;
00256     }
00257 
00258     Q_UINT16 numFunction;
00259     Q_UINT32 size;
00260     int  bufferOffset, j;
00261 
00262     // buffer with functions
00263     QDataStream st( mBuffer );
00264     st.setByteOrder( QDataStream::LittleEndian );
00265 
00266     mReadWmf = readWmf;
00267     mWindow = mBBox;
00268     if ( mReadWmf->begin() ) {
00269         // play wmf functions
00270         mBuffer->at( mOffsetFirstRecord );
00271         numFunction = j = 1;
00272         mWinding = false;
00273 
00274         while ( ( numFunction ) && ( !mStackOverflow ) ) {
00275             bufferOffset = mBuffer->at();
00276             st >> size >> numFunction;
00277 
00282             numFunction &= 0xFF;
00283             if ( numFunction > 0x5F ) {
00284                 numFunction -= 0x90;
00285             }
00286             if ( (numFunction > 111) || (koWmfFunc[ numFunction ].method == 0) ) {
00287                 // function outside WMF specification
00288                 kdDebug() << "KoWmfReadPrivate::paint : BROKEN WMF file" << endl;
00289                 mValid = false;    
00290                 break;
00291             }
00292 
00293             if ( mNbrFunc ) {
00294                 // debug mode
00295                 if ( (j+12) > mNbrFunc ) {
00296                     // output last 12 functions
00297                     int offBuff = mBuffer->at();
00298                     Q_UINT16 param;
00299 
00300                     kdDebug() <<  j << " : " << numFunction << " : ";
00301                     for ( Q_UINT16 i=0 ; i < (size-3) ; i++ ) {
00302                         st >> param;
00303                         kdDebug() <<  param << " ";
00304                     }
00305                     kdDebug() <<  endl;
00306                     mBuffer->at( offBuff );
00307                 }
00308                 if ( j >= mNbrFunc ) {
00309                     break;
00310                 }
00311                 j++;
00312             }
00313 
00314             // execute the function
00315             (this->*koWmfFunc[ numFunction ].method)( size, st );
00316 
00317             mBuffer->at( bufferOffset + (size<<1) );
00318         }
00319 
00320         mReadWmf->end();
00321     }
00322 
00323     for ( int i=0 ; i < mNbrObject ; i++ ) {
00324         if ( mObjHandleTab[ i ] != 0 )
00325             delete mObjHandleTab[ i ];
00326     }
00327     delete[] mObjHandleTab;
00328     mObjHandleTab = 0;
00329 
00330     return true;
00331 }
00332 
00333 
00334 //-----------------------------------------------------------------------------
00335 // Metafile painter methods
00336 
00337 void KoWmfReadPrivate::setWindowOrg( Q_UINT32, QDataStream& stream )
00338 {
00339     Q_INT16 top, left;
00340 
00341     stream >> top >> left;
00342     mReadWmf->setWindowOrg( left, top );
00343     mWindow.setLeft( left );
00344     mWindow.setTop( top );
00345 //    kdDebug() << "Org : (" << left << ", "  << top << ")  " << endl;
00346 }
00347 
00348 /*  TODO : deeper look in negative width and height
00349 */
00350 
00351 void KoWmfReadPrivate::setWindowExt( Q_UINT32, QDataStream& stream )
00352 {
00353     Q_INT16 width, height;
00354 
00355     // negative value allowed for width and height
00356     stream >> height >> width;
00357     mReadWmf->setWindowExt( width, height );
00358     mWindow.setWidth( width );
00359     mWindow.setHeight( height );
00360 //    kdDebug() << "Ext : (" << width << ", "  << height << ") "<< endl;
00361 }
00362 
00363 
00364 void KoWmfReadPrivate::OffsetWindowOrg( Q_UINT32, QDataStream &stream )
00365 {
00366     Q_INT16 offTop, offLeft;
00367     
00368     stream >> offTop >> offLeft;
00369     mReadWmf->setWindowOrg( mWindow.left() + offLeft, mWindow.top() + offTop );
00370     mWindow.setLeft( mWindow.left() + offLeft );
00371     mWindow.setTop( mWindow.top() + offTop );
00372 }
00373 
00374 
00375 void KoWmfReadPrivate::ScaleWindowExt( Q_UINT32, QDataStream &stream )
00376 {
00377     Q_INT16 width, height;
00378     Q_INT16 heightDenom, heightNum, widthDenom, widthNum;
00379     
00380     stream >> heightDenom >> heightNum >> widthDenom >> widthNum;
00381 
00382     if ( ( widthDenom != 0 ) && ( heightDenom != 0 ) ) {
00383         width = (mWindow.width() * widthNum) / widthDenom;
00384         height = (mWindow.height() * heightNum) / heightDenom;
00385         mReadWmf->setWindowExt( width, height );
00386         mWindow.setWidth( width );
00387         mWindow.setHeight( height );
00388     }
00389 //    kdDebug() << "KoWmfReadPrivate::ScaleWindowExt : " << widthDenom << "  " << heightDenom << endl;
00390 }
00391 
00392 
00393 //-----------------------------------------------------------------------------
00394 // Drawing
00395 
00396 void KoWmfReadPrivate::lineTo( Q_UINT32, QDataStream& stream )
00397 {
00398     Q_INT16 top, left;
00399 
00400     stream >> top >> left;
00401     mReadWmf->lineTo( left, top );
00402 }
00403 
00404 
00405 void KoWmfReadPrivate::moveTo( Q_UINT32, QDataStream& stream )
00406 {
00407     Q_INT16 top, left;
00408 
00409     stream >> top >> left;
00410     mReadWmf->moveTo( left, top );
00411 }
00412 
00413 
00414 void KoWmfReadPrivate::ellipse( Q_UINT32, QDataStream& stream )
00415 {
00416     Q_INT16 top, left, right, bottom;
00417 
00418     stream >> bottom >> right >> top >> left;
00419     mReadWmf->drawEllipse( left, top, right-left, bottom-top );
00420 }
00421 
00422 
00423 void KoWmfReadPrivate::polygon( Q_UINT32, QDataStream& stream )
00424 {
00425     Q_UINT16 num;
00426 
00427     stream >> num;
00428 
00429     QPointArray pa( num );
00430 
00431     pointArray( stream, pa );
00432     mReadWmf->drawPolygon( pa, mWinding );
00433 }
00434 
00435 
00436 void KoWmfReadPrivate::polyPolygon( Q_UINT32, QDataStream& stream )
00437 {
00438     Q_UINT16 numberPoly;
00439     Q_UINT16 sizePoly;
00440     QPtrList<QPointArray> listPa;
00441 
00442     stream >> numberPoly;
00443     
00444     listPa.setAutoDelete( true );
00445     for ( int i=0 ; i < numberPoly ; i++ ) {
00446         stream >> sizePoly;
00447         listPa.append( new QPointArray( sizePoly ) );
00448     }
00449 
00450     // list of point array
00451     QPointArray *pa;
00452     for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
00453         pointArray( stream, *pa );
00454     }
00455 
00456     // draw polygon's
00457     mReadWmf->drawPolyPolygon( listPa, mWinding );
00458     listPa.clear();
00459 }
00460 
00461 
00462 void KoWmfReadPrivate::polyline( Q_UINT32, QDataStream& stream )
00463 {
00464     Q_UINT16 num;
00465 
00466     stream >> num;
00467     QPointArray pa( num );
00468 
00469     pointArray( stream, pa );
00470     mReadWmf->drawPolyline( pa );
00471 }
00472 
00473 
00474 void KoWmfReadPrivate::rectangle( Q_UINT32, QDataStream& stream )
00475 {
00476     Q_INT16 top, left, right, bottom;
00477 
00478     stream >> bottom >> right >> top >> left;
00479     mReadWmf->drawRect( left, top, right-left, bottom-top );
00480 }
00481 
00482 
00483 void KoWmfReadPrivate::roundRect( Q_UINT32, QDataStream& stream )
00484 {
00485     int xRnd = 0, yRnd = 0;
00486     Q_UINT16 widthCorner, heightCorner;
00487     Q_INT16  top, left, right, bottom;
00488 
00489     stream >> heightCorner >> widthCorner;
00490     stream >> bottom >> right >> top >> left;
00491 
00492     // convert (widthCorner, heightCorner) in percentage
00493     if ( (right - left) != 0  )
00494         xRnd = (widthCorner * 100) / (right - left);
00495     if ( (bottom - top) != 0  )
00496         yRnd = (heightCorner * 100) / (bottom - top);
00497 
00498     mReadWmf->drawRoundRect( left, top, right-left, bottom-top, xRnd, yRnd );
00499 }
00500 
00501 
00502 void KoWmfReadPrivate::arc( Q_UINT32, QDataStream& stream )
00503 {
00504     int xCenter, yCenter, angleStart, aLength;
00505     Q_INT16  topEnd, leftEnd, topStart, leftStart;
00506     Q_INT16  top, left, right, bottom;
00507 
00508     stream >> topEnd >> leftEnd >> topStart >> leftStart;
00509     stream >> bottom >> right >> top >> left;
00510 
00511     xCenter = left + ((right-left) / 2);
00512     yCenter = top + ((bottom-top) / 2);
00513     xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00514 
00515     mReadWmf->drawArc( left, top, right-left, bottom-top, angleStart, aLength);
00516 }
00517 
00518 
00519 void KoWmfReadPrivate::chord( Q_UINT32, QDataStream& stream )
00520 {
00521     int xCenter, yCenter, angleStart, aLength;
00522     Q_INT16  topEnd, leftEnd, topStart, leftStart;
00523     Q_INT16  top, left, right, bottom;
00524 
00525     stream >> topEnd >> leftEnd >> topStart >> leftStart;
00526     stream >> bottom >> right >> top >> left;
00527 
00528     xCenter = left + ((right-left) / 2);
00529     yCenter = top + ((bottom-top) / 2);
00530     xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00531 
00532     mReadWmf->drawChord( left, top, right-left, bottom-top, angleStart, aLength);
00533 }
00534 
00535 
00536 void KoWmfReadPrivate::pie( Q_UINT32, QDataStream& stream )
00537 {
00538     int xCenter, yCenter, angleStart, aLength;
00539     Q_INT16  topEnd, leftEnd, topStart, leftStart;
00540     Q_INT16  top, left, right, bottom;
00541 
00542     stream >> topEnd >> leftEnd >> topStart >> leftStart;
00543     stream >> bottom >> right >> top >> left;
00544 
00545     xCenter = left + ((right-left) / 2);
00546     yCenter = top + ((bottom-top) / 2);
00547     xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00548 
00549     mReadWmf->drawPie( left, top, right-left, bottom-top, angleStart, aLength);
00550 }
00551 
00552 
00553 void KoWmfReadPrivate::setPolyFillMode( Q_UINT32, QDataStream& stream )
00554 {
00555     Q_UINT16 winding;
00556 
00557     stream >> winding;
00558     mWinding = (winding != 0);
00559 }
00560 
00561 
00562 void KoWmfReadPrivate::setBkColor( Q_UINT32, QDataStream& stream )
00563 {
00564     Q_UINT32 color;
00565 
00566     stream >> color;
00567     mReadWmf->setBackgroundColor( qtColor( color ) );
00568 }
00569 
00570 
00571 void KoWmfReadPrivate::setBkMode( Q_UINT32, QDataStream& stream )
00572 {
00573     Q_UINT16 bkMode;
00574 
00575     stream >> bkMode;
00576     if ( bkMode == 1 )
00577         mReadWmf->setBackgroundMode( Qt::TransparentMode );
00578     else
00579         mReadWmf->setBackgroundMode( Qt::OpaqueMode );
00580 }
00581 
00582 
00583 void KoWmfReadPrivate::setPixel( Q_UINT32, QDataStream& stream )
00584 {
00585     Q_INT16  top, left;
00586     Q_UINT32 color;
00587 
00588     stream >> color >> top >> left;
00589 
00590     QPen oldPen = mReadWmf->pen();    
00591     QPen pen = oldPen;    
00592     pen.setColor( qtColor( color ) );
00593     mReadWmf->setPen( pen );
00594     mReadWmf->moveTo( left, top );
00595     mReadWmf->lineTo( left, top );
00596     mReadWmf->setPen( oldPen );
00597 }
00598 
00599 
00600 void KoWmfReadPrivate::setRop( Q_UINT32, QDataStream& stream )
00601 {
00602     Q_UINT16  rop;
00603 
00604     stream >> rop;
00605     mReadWmf->setRasterOp( winToQtRaster( rop ) );
00606 }
00607 
00608 
00609 void KoWmfReadPrivate::saveDC( Q_UINT32, QDataStream& )
00610 {
00611     mReadWmf->save();
00612 }
00613 
00614 
00615 void KoWmfReadPrivate::restoreDC( Q_UINT32, QDataStream& stream )
00616 {
00617     Q_INT16  num;
00618 
00619     stream >> num;
00620     for ( int i=0; i > num ; i-- )
00621         mReadWmf->restore();
00622 }
00623 
00624 
00625 void KoWmfReadPrivate::intersectClipRect( Q_UINT32, QDataStream& stream )
00626 {
00627     Q_INT16 top, left, right, bottom;
00628 
00629     stream >> bottom >> right >> top >> left;
00630 
00631     QRegion region = mReadWmf->clipRegion();
00632     QRegion newRegion( left, top, right-left, bottom-top );
00633     if ( region.isEmpty() ) {
00634         region = newRegion;
00635     }
00636     else {
00637         region = region.intersect( newRegion );
00638     }
00639 
00640     mReadWmf->setClipRegion( region );
00641 }
00642 
00643 
00644 void KoWmfReadPrivate::excludeClipRect( Q_UINT32, QDataStream& stream )
00645 {
00646     Q_INT16 top, left, right, bottom;
00647 
00648     stream >> bottom >> right >> top >> left;
00649 
00650     QRegion region = mReadWmf->clipRegion();
00651     QRegion newRegion( left, top, right-left, bottom-top );
00652     if ( region.isEmpty() ) {
00653         region = newRegion;
00654     }
00655     else {
00656         region = region.subtract( newRegion );
00657     }
00658 
00659     mReadWmf->setClipRegion( region );
00660 }
00661 
00662 
00663 //-----------------------------------------------------------------------------
00664 // Text
00665 
00666 void KoWmfReadPrivate::setTextColor( Q_UINT32, QDataStream& stream )
00667 {
00668     Q_UINT32 color;
00669     
00670     stream >> color;
00671     mTextColor = qtColor( color );
00672 }
00673 
00674 
00675 void KoWmfReadPrivate::setTextAlign( Q_UINT32, QDataStream& stream )
00676 {
00677     stream >> mTextAlign;
00678 }
00679 
00680 
00681 void KoWmfReadPrivate::textOut( Q_UINT32, QDataStream& )
00682 {
00683     if ( mNbrFunc ) {
00684         kdDebug() << "textOut : unimplemented " << endl;
00685     }
00686 }
00687 
00688 
00689 void KoWmfReadPrivate::extTextOut( Q_UINT32 , QDataStream&  )
00690 {
00691     if ( mNbrFunc ) {
00692         kdDebug() << "extTextOut : unimplemented " << endl;
00693     }
00694 }
00695 
00696 
00697 
00698 //-----------------------------------------------------------------------------
00699 // Bitmap
00700 
00701 void KoWmfReadPrivate::SetStretchBltMode( Q_UINT32, QDataStream& )
00702 {
00703     if ( mNbrFunc ) {
00704         kdDebug() << "SetStretchBltMode : unimplemented " << endl;
00705     }
00706 }
00707 
00708 
00709 void KoWmfReadPrivate::dibBitBlt( Q_UINT32 size, QDataStream& stream )
00710 {
00711     Q_UINT32 raster;
00712     Q_INT16  topSrc, leftSrc, widthSrc, heightSrc;
00713     Q_INT16  topDst, leftDst;
00714 
00715     stream >> raster;
00716     stream >> topSrc >> leftSrc >> heightSrc >> widthSrc;
00717     stream >> topDst >> leftDst;
00718 
00719     if ( size > 11 ) {    // DIB image
00720         QImage bmpSrc;
00721 
00722         if ( dibToBmp( bmpSrc, stream, (size - 11) * 2 ) ) {
00723             mReadWmf->setRasterOp( winToQtRaster( raster )  );
00724 
00725             mReadWmf->save();
00726             if ( widthSrc < 0 ) {
00727                 // negative width => horizontal flip
00728                 QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00729                 mReadWmf->setWorldMatrix( m, true );
00730             }
00731             if ( heightSrc < 0 ) {
00732                 // negative height => vertical flip
00733                 QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00734                 mReadWmf->setWorldMatrix( m, true );
00735             }
00736             mReadWmf->drawImage( leftDst, topDst, bmpSrc, leftSrc, topSrc, widthSrc, heightSrc );
00737             mReadWmf->restore();
00738         }
00739     }
00740     else {
00741         kdDebug() << "KoWmfReadPrivate::dibBitBlt without image not implemented " << endl;
00742     }
00743 }
00744 
00745 
00746 void KoWmfReadPrivate::dibStretchBlt( Q_UINT32 size, QDataStream& stream )
00747 {
00748     Q_UINT32 raster;
00749     Q_INT16  topSrc, leftSrc, widthSrc, heightSrc;
00750     Q_INT16  topDst, leftDst, widthDst, heightDst;
00751     QImage   bmpSrc;
00752 
00753     stream >> raster;
00754     stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
00755     stream >> heightDst >> widthDst >> topDst >> leftDst;
00756 
00757     if ( dibToBmp( bmpSrc, stream, (size - 13) * 2 ) ) {
00758         mReadWmf->setRasterOp( winToQtRaster( raster )  );
00759 
00760         mReadWmf->save();
00761         if ( widthDst < 0 ) {
00762             // negative width => horizontal flip
00763             QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00764             mReadWmf->setWorldMatrix( m, true );
00765         }
00766         if ( heightDst < 0 ) {
00767             // negative height => vertical flip
00768             QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00769             mReadWmf->setWorldMatrix( m, true );
00770         }
00771         bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
00772         // TODO: scale the bitmap : QImage::scale(widthDst, heightDst)
00773         // is actually too slow
00774 
00775         mReadWmf->drawImage( leftDst, topDst, bmpSrc );
00776         mReadWmf->restore();
00777     }
00778 }
00779 
00780 
00781 void KoWmfReadPrivate::stretchDib( Q_UINT32 size, QDataStream& stream )
00782 {
00783     Q_UINT32 raster;
00784     Q_INT16  arg, topSrc, leftSrc, widthSrc, heightSrc;
00785     Q_INT16  topDst, leftDst, widthDst, heightDst;
00786     QImage   bmpSrc;
00787 
00788     stream >> raster >> arg;
00789     stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
00790     stream >> heightDst >> widthDst >> topDst >> leftDst;
00791 
00792     if ( dibToBmp( bmpSrc, stream, (size - 14) * 2 ) ) {
00793         mReadWmf->setRasterOp( winToQtRaster( raster )  );
00794 
00795         mReadWmf->save();
00796         if ( widthDst < 0 ) {
00797             // negative width => horizontal flip
00798             QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00799             mReadWmf->setWorldMatrix( m, true );
00800         }
00801         if ( heightDst < 0 ) {
00802             // negative height => vertical flip
00803             QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00804             mReadWmf->setWorldMatrix( m, true );
00805         }
00806         bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
00807         // TODO: scale the bitmap ( QImage::scale(param[ 8 ], param[ 7 ]) is actually too slow )
00808 
00809         mReadWmf->drawImage( leftDst, topDst, bmpSrc );
00810         mReadWmf->restore();
00811     }
00812 }
00813 
00814 
00815 void KoWmfReadPrivate::dibCreatePatternBrush( Q_UINT32 size, QDataStream& stream )
00816 {
00817     KoWmfPatternBrushHandle* handle = new KoWmfPatternBrushHandle;
00818     
00819     if ( addHandle( handle ) ) {
00820         Q_UINT32 arg;
00821         QImage bmpSrc;
00822 
00823         stream >> arg;
00824         if ( dibToBmp( bmpSrc, stream, (size - 5) * 2 ) ) {
00825             handle->image = bmpSrc;
00826             handle->brush.setPixmap( handle->image );
00827         }
00828         else {
00829             kdDebug() << "KoWmfReadPrivate::dibCreatePatternBrush : incorrect DIB image" << endl;
00830         }
00831     }
00832 }
00833 
00834 
00835 //-----------------------------------------------------------------------------
00836 // Object handle
00837 
00838 void KoWmfReadPrivate::selectObject( Q_UINT32, QDataStream& stream )
00839 {
00840     Q_UINT16 idx;
00841 
00842     stream >> idx;
00843     if ( (idx < mNbrObject) && (mObjHandleTab[ idx ] != 0) )
00844         mObjHandleTab[ idx ]->apply( mReadWmf );
00845     else
00846         kdDebug() << "KoWmfReadPrivate::selectObject : selection of an empty object" << endl;
00847 }
00848 
00849 
00850 void KoWmfReadPrivate::deleteObject( Q_UINT32, QDataStream& stream )
00851 {
00852     Q_UINT16 idx;
00853 
00854     stream >> idx;
00855     deleteHandle( idx );
00856 }
00857 
00858 
00859 void KoWmfReadPrivate::createEmptyObject()
00860 {
00861     // allocation of an empty object (to keep object counting in sync)
00862     KoWmfPenHandle* handle = new KoWmfPenHandle;
00863 
00864     addHandle( handle );
00865 }
00866 
00867 
00868 void KoWmfReadPrivate::createBrushIndirect( Q_UINT32, QDataStream& stream )
00869 {
00870     Qt::BrushStyle style;
00871     Q_UINT16 sty, arg2;
00872     Q_UINT32 color;
00873     KoWmfBrushHandle* handle = new KoWmfBrushHandle;
00874 
00875     if ( addHandle( handle ) ) {
00876         stream >> sty >> color >> arg2;
00877 
00878         if ( sty == 2 ) {
00879             if ( arg2 < 6 )
00880                 style = koWmfHatchedStyleBrush[ arg2 ];
00881             else
00882             {
00883                 kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid hatched brush " << arg2 << endl;
00884                 style = Qt::SolidPattern;
00885             }
00886         }
00887         else {
00888             if ( sty < 9 )
00889                 style = koWmfStyleBrush[ sty ];
00890             else {
00891                 kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid brush " << sty << endl;
00892                 style = Qt::SolidPattern;
00893             }
00894         }
00895         handle->brush.setStyle( style );
00896         handle->brush.setColor( qtColor( color ) );
00897     }
00898 }
00899 
00900 
00901 void KoWmfReadPrivate::createPenIndirect( Q_UINT32, QDataStream& stream )
00902 {
00903     // TODO: userStyle and alternateStyle
00904     Qt::PenStyle penStyle;
00905     Q_UINT32 color;
00906     Q_UINT16 style, width, arg;
00907 
00908     KoWmfPenHandle* handle = new KoWmfPenHandle;
00909 
00910     if ( addHandle( handle ) ) {
00911         stream >> style >> width >> arg >> color;
00912 
00913         if ( style < 7 )
00914             penStyle=koWmfStylePen[ style ];
00915         else {
00916             kdDebug() << "KoWmfReadPrivate::createPenIndirect: invalid pen " << style << endl;
00917             penStyle = Qt::SolidLine;
00918         }
00919 
00920         handle->pen.setStyle( penStyle );
00921         handle->pen.setColor( qtColor( color ) );
00922         handle->pen.setCapStyle( Qt::RoundCap );
00923         handle->pen.setWidth( width );
00924     }
00925 }
00926 
00927 
00928 void KoWmfReadPrivate::createFontIndirect( Q_UINT32 size, QDataStream& stream )
00929 {
00930     Q_INT16  pointSize, rotation;
00931     Q_UINT16 weight, property, fixedPitch, arg;
00932 
00933     KoWmfFontHandle* handle = new KoWmfFontHandle;
00934 
00935     if ( addHandle( handle ) ) {
00936         stream >> pointSize >> arg;
00937         stream >> rotation >> arg;
00938         stream >> weight >> property >> arg >> arg;
00939         stream >> fixedPitch;
00940 
00941         // text rotation (in 1/10 degree)
00942         // TODO: memorisation of rotation in object Font
00943         mTextRotation = -rotation / 10;
00944         handle->font.setFixedPitch( ((fixedPitch & 0x01) == 0) );
00945         // TODO: investigation why some test case need -2
00946         // size of font in logical point
00947         handle->font.setPointSize( QABS(pointSize) - 2 );
00948         handle->font.setWeight( (weight >> 3) );
00949         handle->font.setItalic( (property & 0x01) );
00950         handle->font.setUnderline( (property & 0x100) );
00951 
00952         // font name
00953         int    maxChar = (size-12) * 2;
00954         char*  nameFont = new char[maxChar];
00955         stream.readRawBytes( nameFont, maxChar );
00956         handle->font.setFamily( nameFont );
00957         delete[] nameFont;
00958     }
00959 }
00960 
00961 
00962 //-----------------------------------------------------------------------------
00963 // Misc functions
00964 
00965 void KoWmfReadPrivate::end( Q_UINT32, QDataStream& )
00966 {
00967 }
00968 
00969 Q_UINT16 KoWmfReadPrivate::calcCheckSum( WmfPlaceableHeader* apmfh )
00970 {
00971     Q_UINT16*  lpWord;
00972     Q_UINT16   wResult, i;
00973 
00974     // Start with the first word
00975     wResult = *( lpWord = ( Q_UINT16* )( apmfh ) );
00976     // XOR in each of the other 9 words
00977     for( i=1; i<=9; i++ )
00978     {
00979         wResult ^= lpWord[ i ];
00980     }
00981     return wResult;
00982 }
00983 
00984 
00985 void KoWmfReadPrivate::notyet( Q_UINT32, QDataStream& )
00986 {
00987     if ( mNbrFunc ) {
00988         kdDebug() << "unimplemented " << endl;
00989     }
00990 }
00991 
00992 void KoWmfReadPrivate::region( Q_UINT32, QDataStream& )
00993 {
00994     if ( mNbrFunc ) {
00995         kdDebug() << "region : unimplemented " << endl;
00996     }
00997 }
00998 
00999 void KoWmfReadPrivate::palette( Q_UINT32, QDataStream& )
01000 {
01001     if ( mNbrFunc ) {
01002         kdDebug() << "palette : unimplemented " << endl;
01003     }
01004 }
01005 
01006 void KoWmfReadPrivate::escape( Q_UINT32, QDataStream& )
01007 {
01008     if ( mNbrFunc ) {
01009         kdDebug() << "escape : unimplemented " << endl;
01010     }
01011 }
01012 
01013 void KoWmfReadPrivate::setRelAbs( Q_UINT32, QDataStream& )
01014 {
01015     if ( mNbrFunc ) {
01016         kdDebug() << "setRelAbs : unimplemented " << endl;
01017     }
01018 }
01019 
01020 void KoWmfReadPrivate::setMapMode( Q_UINT32, QDataStream& )
01021 {
01022     if ( mNbrFunc ) {
01023         kdDebug() << "setMapMode : unimplemented " << endl;
01024     }
01025 }
01026 
01027 void KoWmfReadPrivate::extFloodFill( Q_UINT32, QDataStream&  )
01028 {
01029     if ( mNbrFunc ) {
01030         kdDebug() << "extFloodFill : unimplemented " << endl;
01031     }
01032 }
01033 
01034 void KoWmfReadPrivate::startDoc( Q_UINT32, QDataStream&  )
01035 {
01036     if ( mNbrFunc ) {
01037         kdDebug() << "startDoc : unimplemented " << endl;
01038     }
01039 }
01040 
01041 void KoWmfReadPrivate::startPage( Q_UINT32, QDataStream&  )
01042 {
01043     if ( mNbrFunc ) {
01044         kdDebug() << "startPage : unimplemented " << endl;
01045     }
01046 }
01047 
01048 void KoWmfReadPrivate::endDoc( Q_UINT32, QDataStream&  )
01049 {
01050     if ( mNbrFunc ) {
01051         kdDebug() << "endDoc : unimplemented " << endl;
01052     }
01053 }
01054 
01055 void KoWmfReadPrivate::endPage( Q_UINT32, QDataStream&  )
01056 {
01057     if ( mNbrFunc ) {
01058         kdDebug() << "endPage : unimplemented " << endl;
01059     }
01060 }
01061 
01062 void KoWmfReadPrivate::resetDC( Q_UINT32, QDataStream&  )
01063 {
01064     if ( mNbrFunc ) {
01065         kdDebug() << "resetDC : unimplemented " << endl;
01066     }
01067 }
01068 
01069 void KoWmfReadPrivate::bitBlt( Q_UINT32, QDataStream&  )
01070 {
01071     if ( mNbrFunc ) {
01072         kdDebug() << "bitBlt : unimplemented " << endl;
01073     }
01074 }
01075 
01076 void KoWmfReadPrivate::setDibToDev( Q_UINT32, QDataStream&  )
01077 {
01078     if ( mNbrFunc ) {
01079         kdDebug() << "setDibToDev : unimplemented " << endl;
01080     }
01081 }
01082 
01083 void KoWmfReadPrivate::createBrush( Q_UINT32, QDataStream&  )
01084 {
01085     if ( mNbrFunc ) {
01086         kdDebug() << "createBrush : unimplemented " << endl;
01087     }
01088 }
01089 
01090 void KoWmfReadPrivate::createPatternBrush( Q_UINT32, QDataStream&  )
01091 {
01092     if ( mNbrFunc ) {
01093         kdDebug() << "createPatternBrush : unimplemented " << endl;
01094     }
01095 }
01096 
01097 void KoWmfReadPrivate::createBitmap( Q_UINT32, QDataStream&  )
01098 {
01099     if ( mNbrFunc ) {
01100         kdDebug() << "createBitmap : unimplemented " << endl;
01101     }
01102 }
01103 
01104 void KoWmfReadPrivate::createBitmapIndirect( Q_UINT32, QDataStream&  )
01105 {
01106     createEmptyObject();
01107     if ( mNbrFunc ) {
01108         kdDebug() << "createBitmapIndirect : unimplemented " << endl;
01109     }
01110 }
01111 
01112 void KoWmfReadPrivate::createPalette( Q_UINT32, QDataStream&  )
01113 {
01114     createEmptyObject();
01115     if ( mNbrFunc ) {
01116         kdDebug() << "createPalette : unimplemented " << endl;
01117     }
01118 }
01119 
01120 void KoWmfReadPrivate::createRegion( Q_UINT32, QDataStream&  )
01121 {
01122     createEmptyObject();
01123     if ( mNbrFunc ) {
01124         kdDebug() << "createRegion : unimplemented " << endl;
01125     }
01126 }
01127 
01128 
01129 
01130 //-----------------------------------------------------------------------------
01131 // Utilities and conversion Wmf -> Qt
01132 
01133 bool KoWmfReadPrivate::addHandle( KoWmfHandle* handle )
01134 {
01135     int idx;
01136 
01137     for ( idx=0; idx < mNbrObject ; idx++ ) {
01138         if ( mObjHandleTab[ idx ] == 0 )  break;
01139     }
01140 
01141     if ( idx < mNbrObject ) {
01142         mObjHandleTab[ idx ] = handle;
01143         return true;
01144     }
01145     else {
01146         delete handle;
01147         mStackOverflow = true;
01148         kdDebug() << "KoWmfReadPrivate::addHandle : stack overflow = broken file !" << endl;
01149         return false;
01150     }
01151 }
01152 
01153 
01154 void KoWmfReadPrivate::deleteHandle( int idx )
01155 {
01156     if ( (idx < mNbrObject) && (mObjHandleTab[idx] != 0) ) {
01157         delete mObjHandleTab[ idx ];
01158         mObjHandleTab[ idx ] = 0;
01159     }
01160     else {
01161         kdDebug() << "KoWmfReadPrivate::deletehandle() : bad index number" << endl;
01162     }
01163 }
01164 
01165 
01166 void KoWmfReadPrivate::pointArray( QDataStream& stream, QPointArray& pa )
01167 {
01168     Q_INT16 left, top;
01169     int  i, max;
01170 
01171     for ( i=0, max=pa.size() ; i < max ; i++ ) {
01172         stream >> left >> top;
01173         pa.setPoint( i, left, top );
01174     }
01175 }
01176 
01177 
01178 void KoWmfReadPrivate::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
01179 {
01180     double aStart, aLength;
01181 
01182     aStart = atan2( yStart,  xStart );
01183     aLength = atan2( yEnd, xEnd ) - aStart;
01184 
01185     angleStart = (int)((aStart * 2880) / 3.14166);
01186     angleLength = (int)((aLength * 2880) / 3.14166);
01187     if ( angleLength < 0 ) angleLength = 5760 + angleLength;
01188 }
01189 
01190 
01191 Qt::RasterOp  KoWmfReadPrivate::winToQtRaster( Q_UINT16 param ) const
01192 {
01193     if ( param < 17 )
01194         return koWmfOpTab16[ param ];
01195     else
01196         return Qt::CopyROP;
01197 }
01198 
01199 
01200 Qt::RasterOp  KoWmfReadPrivate::winToQtRaster( Q_UINT32 param ) const
01201 {
01202     /* TODO: Ternary raster operations
01203     0x00C000CA  dest = (source AND pattern)
01204     0x00F00021  dest = pattern
01205     0x00FB0A09  dest = DPSnoo
01206     0x005A0049  dest = pattern XOR dest   */
01207     int i;
01208 
01209     for ( i=0 ; i < 15 ; i++ ) {
01210         if ( koWmfOpTab32[ i ].winRasterOp == param )  break;
01211     }
01212 
01213     if ( i < 15 )
01214         return koWmfOpTab32[ i ].qtRasterOp;
01215     else
01216         return Qt::CopyROP;
01217 }
01218 
01219 
01220 bool KoWmfReadPrivate::dibToBmp( QImage& bmp, QDataStream& stream, Q_UINT32 size )
01221 {
01222     typedef struct _BMPFILEHEADER {
01223         Q_UINT16 bmType;
01224         Q_UINT32 bmSize;
01225         Q_UINT16 bmReserved1;
01226         Q_UINT16 bmReserved2;
01227         Q_UINT32 bmOffBits;
01228     }  BMPFILEHEADER;
01229 
01230     int sizeBmp = size + 14;
01231 
01232     QByteArray pattern( sizeBmp );       // BMP header and DIB data
01233     pattern.fill(0);
01234     stream.readRawBytes( &pattern[ 14 ], size );
01235 
01236     // add BMP header
01237     BMPFILEHEADER* bmpHeader;
01238     bmpHeader = (BMPFILEHEADER*)(pattern.data());
01239     bmpHeader->bmType = 0x4D42;
01240     bmpHeader->bmSize = sizeBmp;
01241 
01242 //    if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
01243     if ( !bmp.loadFromData( pattern, "BMP" ) ) {
01244         kdDebug() << "KoWmfReadPrivate::dibToBmp: invalid bitmap " << endl;
01245         return false;
01246     }
01247     else {
01248         return true;
01249     }
01250 }
01251 
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Mar 20 14:25:28 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003