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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:28 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003