F:/KPlato/koffice/libs/kwmf/kowmfreadprivate.cc

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

Généré le Wed Nov 22 23:41:13 2006 pour KPlato par  doxygen 1.5.1-p1