KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1252 lines
33KB

  1. /* This file is part of the KDE libraries
  2. * Copyright (c) 1998 Stefan Taferner
  3. * 2001/2003 thierry lorthiois (lorthioist@wanadoo.fr)
  4. * With the help of WMF documentation by Caolan Mc Namara
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License version 2 as published by the Free Software Foundation.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Library General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Library General Public License
  16. * along with this library; see the file COPYING.LIB. If not, write to
  17. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. * Boston, MA 02110-1301, USA.
  19. */
  20. #include <math.h>
  21. #include <tqfileinfo.h>
  22. #include <tqimage.h>
  23. #include <tqwmatrix.h>
  24. #include <tqptrlist.h>
  25. #include <tqpointarray.h>
  26. #include <tqdatastream.h>
  27. #include <kdebug.h>
  28. #include "kowmfreadprivate.h"
  29. #include "kowmfread.h"
  30. KoWmfReadPrivate::KoWmfReadPrivate()
  31. {
  32. mNbrFunc = 0;
  33. mValid = false;
  34. mStandard = false;
  35. mPlaceable = false;
  36. mEnhanced = false;
  37. mBuffer = 0;
  38. mObjHandleTab = 0;
  39. }
  40. KoWmfReadPrivate::~KoWmfReadPrivate()
  41. {
  42. if ( mObjHandleTab != 0 ) {
  43. for ( int i=0 ; i < mNbrObject ; i++ ) {
  44. if ( mObjHandleTab[i] != 0 )
  45. delete mObjHandleTab[i];
  46. }
  47. delete[] mObjHandleTab;
  48. }
  49. if ( mBuffer != 0 ) {
  50. mBuffer->close();
  51. delete mBuffer;
  52. }
  53. }
  54. bool KoWmfReadPrivate::load( const TQByteArray& array )
  55. {
  56. // delete previous buffer
  57. if ( mBuffer != 0 ) {
  58. mBuffer->close();
  59. delete mBuffer;
  60. }
  61. // load into buffer
  62. mBuffer = new TQBuffer( array );
  63. mBuffer->open( IO_ReadOnly );
  64. // read and check the header
  65. WmfEnhMetaHeader eheader;
  66. WmfMetaHeader header;
  67. WmfPlaceableHeader pheader;
  68. unsigned short checksum;
  69. int filePos;
  70. TQDataStream st( mBuffer );
  71. st.setByteOrder( TQDataStream::LittleEndian );
  72. mStackOverflow = mWinding = false;
  73. mTextAlign = mTextRotation = 0;
  74. mTextColor = TQt::black;
  75. mValid = false;
  76. mStandard = false;
  77. mPlaceable = false;
  78. mEnhanced = false;
  79. //----- Read placeable metafile header
  80. st >> pheader.key;
  81. if ( pheader.key==( TQ_UINT32 )APMHEADER_KEY ) {
  82. mPlaceable = true;
  83. st >> pheader.handle;
  84. st >> pheader.left;
  85. st >> pheader.top;
  86. st >> pheader.right;
  87. st >> pheader.bottom;
  88. st >> pheader.inch;
  89. st >> pheader.reserved;
  90. st >> pheader.checksum;
  91. checksum = calcCheckSum( &pheader );
  92. if ( pheader.checksum!=checksum ) {
  93. return false;
  94. }
  95. st >> header.fileType;
  96. st >> header.headerSize;
  97. st >> header.version;
  98. st >> header.fileSize;
  99. st >> header.numOfObjects;
  100. st >> header.maxRecordSize;
  101. st >> header.numOfParameters;
  102. mNbrObject = header.numOfObjects;
  103. mBBox.setLeft( pheader.left );
  104. mBBox.setTop( pheader.top );
  105. mBBox.setRight( pheader.right );
  106. mBBox.setBottom( pheader.bottom );
  107. mDpi = pheader.inch;
  108. }
  109. else {
  110. mBuffer->at( 0 );
  111. //----- Read as enhanced metafile header
  112. filePos = mBuffer->at();
  113. st >> eheader.recordType;
  114. st >> eheader.recordSize;
  115. st >> eheader.boundsLeft;
  116. st >> eheader.boundsTop;
  117. st >> eheader.boundsRight;
  118. st >> eheader.boundsBottom;
  119. st >> eheader.frameLeft;
  120. st >> eheader.frameTop;
  121. st >> eheader.frameRight;
  122. st >> eheader.frameBottom;
  123. st >> eheader.signature;
  124. if ( eheader.signature==ENHMETA_SIGNATURE ) {
  125. mEnhanced = true;
  126. st >> eheader.version;
  127. st >> eheader.size;
  128. st >> eheader.numOfRecords;
  129. st >> eheader.numHandles;
  130. st >> eheader.reserved;
  131. st >> eheader.sizeOfDescription;
  132. st >> eheader.offsetOfDescription;
  133. st >> eheader.numPaletteEntries;
  134. st >> eheader.widthDevicePixels;
  135. st >> eheader.heightDevicePixels;
  136. st >> eheader.widthDeviceMM;
  137. st >> eheader.heightDeviceMM;
  138. }
  139. else {
  140. //----- Read as standard metafile header
  141. mStandard = true;
  142. mBuffer->at( filePos );
  143. st >> header.fileType;
  144. st >> header.headerSize;
  145. st >> header.version;
  146. st >> header.fileSize;
  147. st >> header.numOfObjects;
  148. st >> header.maxRecordSize;
  149. st >> header.numOfParameters;
  150. mNbrObject = header.numOfObjects;
  151. }
  152. }
  153. mOffsetFirstRecord = mBuffer->at();
  154. //----- Test header validity
  155. if ( ((header.headerSize == 9) && (header.numOfParameters == 0)) || (mPlaceable) ) {
  156. // valid wmf file
  157. mValid = true;
  158. }
  159. else {
  160. kdDebug() << "KoWmfReadPrivate : incorrect file format !" << endl;
  161. }
  162. // check bounding rectangle for standard meta file
  163. if ( (mValid) && (mStandard) ) {
  164. TQ_UINT16 numFunction = 1;
  165. TQ_UINT32 size;
  166. bool firstOrg=true, firstExt=true;
  167. // search functions setWindowOrg and setWindowExt
  168. while ( numFunction ) {
  169. filePos = mBuffer->at();
  170. st >> size >> numFunction;
  171. if ( size == 0 ) {
  172. kdDebug() << "KoWmfReadPrivate : incorrect file!" << endl;
  173. mValid = 0;
  174. break;
  175. }
  176. numFunction &= 0xFF;
  177. if ( numFunction == 11 ) {
  178. TQ_INT16 top, left;
  179. st >> top >> left;
  180. if ( firstOrg ) {
  181. firstOrg = false;
  182. mBBox.setLeft( left );
  183. mBBox.setTop( top );
  184. }
  185. else {
  186. if ( left < mBBox.left() ) mBBox.setLeft( left );
  187. if ( top < mBBox.top() ) mBBox.setTop( top );
  188. }
  189. }
  190. if ( numFunction == 12 ) {
  191. TQ_INT16 width, height;
  192. st >> height >> width;
  193. if ( width < 0 ) width = -width;
  194. if ( height < 0 ) height = -height;
  195. if ( firstExt ) {
  196. firstExt = false;
  197. mBBox.setWidth( width );
  198. mBBox.setHeight( height );
  199. }
  200. else {
  201. if ( width > mBBox.width() ) mBBox.setWidth( width );
  202. if ( height > mBBox.height() ) mBBox.setHeight( height );
  203. }
  204. }
  205. mBuffer->at( filePos + (size<<1) );
  206. // ## shouldn't we break from the loop as soon as we found what we were looking for?
  207. }
  208. }
  209. return (mValid);
  210. }
  211. bool KoWmfReadPrivate::play( KoWmfRead* readWmf )
  212. {
  213. if ( !(mValid) ) {
  214. kdDebug() << "KoWmfReadPrivate::play : invalid WMF file" << endl;
  215. return false;
  216. }
  217. if ( mNbrFunc ) {
  218. if ( (mStandard) ) {
  219. kdDebug() << "Standard : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
  220. }
  221. else {
  222. kdDebug() << "DPI : " << mDpi << " : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
  223. kdDebug() << "inch : " << mBBox.width()/mDpi << " " << mBBox.height()/mDpi << endl;
  224. kdDebug() << "mm : " << mBBox.width()*25.4/mDpi << " " << mBBox.height()*25.4/mDpi << endl;
  225. }
  226. kdDebug() << mValid << " " << mStandard << " " << mPlaceable << endl;
  227. }
  228. // stack of handle
  229. mObjHandleTab = new KoWmfHandle* [ mNbrObject ];
  230. for ( int i=0; i < mNbrObject ; i++ ) {
  231. mObjHandleTab[ i ] = 0;
  232. }
  233. TQ_UINT16 numFunction;
  234. TQ_UINT32 size;
  235. int bufferOffset, j;
  236. // buffer with functions
  237. TQDataStream st( mBuffer );
  238. st.setByteOrder( TQDataStream::LittleEndian );
  239. mReadWmf = readWmf;
  240. mWindow = mBBox;
  241. if ( mReadWmf->begin() ) {
  242. // play wmf functions
  243. mBuffer->at( mOffsetFirstRecord );
  244. numFunction = j = 1;
  245. mWinding = false;
  246. while ( ( numFunction ) && ( !mStackOverflow ) ) {
  247. bufferOffset = mBuffer->at();
  248. st >> size >> numFunction;
  249. /**
  250. * mapping between n° function and index of table 'metaFuncTab'
  251. * lower 8 digits of the function => entry in the table
  252. */
  253. numFunction &= 0xFF;
  254. if ( numFunction > 0x5F ) {
  255. numFunction -= 0x90;
  256. }
  257. if ( (numFunction > 111) || (koWmfFunc[ numFunction ].method == 0) ) {
  258. // function outside WMF specification
  259. kdDebug() << "KoWmfReadPrivate::paint : BROKEN WMF file" << endl;
  260. mValid = false;
  261. break;
  262. }
  263. if ( mNbrFunc ) {
  264. // debug mode
  265. if ( (j+12) > mNbrFunc ) {
  266. // output last 12 functions
  267. int offBuff = mBuffer->at();
  268. TQ_UINT16 param;
  269. kdDebug() << j << " : " << numFunction << " : ";
  270. for ( TQ_UINT16 i=0 ; i < (size-3) ; i++ ) {
  271. st >> param;
  272. kdDebug() << param << " ";
  273. }
  274. kdDebug() << endl;
  275. mBuffer->at( offBuff );
  276. }
  277. if ( j >= mNbrFunc ) {
  278. break;
  279. }
  280. j++;
  281. }
  282. // execute the function
  283. (this->*koWmfFunc[ numFunction ].method)( size, st );
  284. mBuffer->at( bufferOffset + (size<<1) );
  285. }
  286. mReadWmf->end();
  287. }
  288. for ( int i=0 ; i < mNbrObject ; i++ ) {
  289. if ( mObjHandleTab[ i ] != 0 )
  290. delete mObjHandleTab[ i ];
  291. }
  292. delete[] mObjHandleTab;
  293. mObjHandleTab = 0;
  294. return true;
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Metafile painter methods
  298. void KoWmfReadPrivate::setWindowOrg( TQ_UINT32, TQDataStream& stream )
  299. {
  300. TQ_INT16 top, left;
  301. stream >> top >> left;
  302. mReadWmf->setWindowOrg( left, top );
  303. mWindow.setLeft( left );
  304. mWindow.setTop( top );
  305. // kdDebug() << "Org : (" << left << ", " << top << ") " << endl;
  306. }
  307. /* TODO : deeper look in negative width and height
  308. */
  309. void KoWmfReadPrivate::setWindowExt( TQ_UINT32, TQDataStream& stream )
  310. {
  311. TQ_INT16 width, height;
  312. // negative value allowed for width and height
  313. stream >> height >> width;
  314. mReadWmf->setWindowExt( width, height );
  315. mWindow.setWidth( width );
  316. mWindow.setHeight( height );
  317. // kdDebug() << "Ext : (" << width << ", " << height << ") "<< endl;
  318. }
  319. void KoWmfReadPrivate::OffsetWindowOrg( TQ_UINT32, TQDataStream &stream )
  320. {
  321. TQ_INT16 offTop, offLeft;
  322. stream >> offTop >> offLeft;
  323. mReadWmf->setWindowOrg( mWindow.left() + offLeft, mWindow.top() + offTop );
  324. mWindow.setLeft( mWindow.left() + offLeft );
  325. mWindow.setTop( mWindow.top() + offTop );
  326. }
  327. void KoWmfReadPrivate::ScaleWindowExt( TQ_UINT32, TQDataStream &stream )
  328. {
  329. TQ_INT16 width, height;
  330. TQ_INT16 heightDenom, heightNum, widthDenom, widthNum;
  331. stream >> heightDenom >> heightNum >> widthDenom >> widthNum;
  332. if ( ( widthDenom != 0 ) && ( heightDenom != 0 ) ) {
  333. width = (mWindow.width() * widthNum) / widthDenom;
  334. height = (mWindow.height() * heightNum) / heightDenom;
  335. mReadWmf->setWindowExt( width, height );
  336. mWindow.setWidth( width );
  337. mWindow.setHeight( height );
  338. }
  339. // kdDebug() << "KoWmfReadPrivate::ScaleWindowExt : " << widthDenom << " " << heightDenom << endl;
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Drawing
  343. void KoWmfReadPrivate::lineTo( TQ_UINT32, TQDataStream& stream )
  344. {
  345. TQ_INT16 top, left;
  346. stream >> top >> left;
  347. mReadWmf->lineTo( left, top );
  348. }
  349. void KoWmfReadPrivate::moveTo( TQ_UINT32, TQDataStream& stream )
  350. {
  351. TQ_INT16 top, left;
  352. stream >> top >> left;
  353. mReadWmf->moveTo( left, top );
  354. }
  355. void KoWmfReadPrivate::ellipse( TQ_UINT32, TQDataStream& stream )
  356. {
  357. TQ_INT16 top, left, right, bottom;
  358. stream >> bottom >> right >> top >> left;
  359. mReadWmf->drawEllipse( left, top, right-left, bottom-top );
  360. }
  361. void KoWmfReadPrivate::polygon( TQ_UINT32, TQDataStream& stream )
  362. {
  363. TQ_UINT16 num;
  364. stream >> num;
  365. TQPointArray pa( num );
  366. pointArray( stream, pa );
  367. mReadWmf->drawPolygon( pa, mWinding );
  368. }
  369. void KoWmfReadPrivate::polyPolygon( TQ_UINT32, TQDataStream& stream )
  370. {
  371. TQ_UINT16 numberPoly;
  372. TQ_UINT16 sizePoly;
  373. TQPtrList<TQPointArray> listPa;
  374. stream >> numberPoly;
  375. listPa.setAutoDelete( true );
  376. for ( int i=0 ; i < numberPoly ; i++ ) {
  377. stream >> sizePoly;
  378. listPa.append( new TQPointArray( sizePoly ) );
  379. }
  380. // list of point array
  381. TQPointArray *pa;
  382. for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
  383. pointArray( stream, *pa );
  384. }
  385. // draw polygon's
  386. mReadWmf->drawPolyPolygon( listPa, mWinding );
  387. listPa.clear();
  388. }
  389. void KoWmfReadPrivate::polyline( TQ_UINT32, TQDataStream& stream )
  390. {
  391. TQ_UINT16 num;
  392. stream >> num;
  393. TQPointArray pa( num );
  394. pointArray( stream, pa );
  395. mReadWmf->drawPolyline( pa );
  396. }
  397. void KoWmfReadPrivate::rectangle( TQ_UINT32, TQDataStream& stream )
  398. {
  399. TQ_INT16 top, left, right, bottom;
  400. stream >> bottom >> right >> top >> left;
  401. mReadWmf->drawRect( left, top, right-left, bottom-top );
  402. }
  403. void KoWmfReadPrivate::roundRect( TQ_UINT32, TQDataStream& stream )
  404. {
  405. int xRnd = 0, yRnd = 0;
  406. TQ_UINT16 widthCorner, heightCorner;
  407. TQ_INT16 top, left, right, bottom;
  408. stream >> heightCorner >> widthCorner;
  409. stream >> bottom >> right >> top >> left;
  410. // convert (widthCorner, heightCorner) in percentage
  411. if ( (right - left) != 0 )
  412. xRnd = (widthCorner * 100) / (right - left);
  413. if ( (bottom - top) != 0 )
  414. yRnd = (heightCorner * 100) / (bottom - top);
  415. mReadWmf->drawRoundRect( left, top, right-left, bottom-top, xRnd, yRnd );
  416. }
  417. void KoWmfReadPrivate::arc( TQ_UINT32, TQDataStream& stream )
  418. {
  419. int xCenter, yCenter, angleStart, aLength;
  420. TQ_INT16 topEnd, leftEnd, topStart, leftStart;
  421. TQ_INT16 top, left, right, bottom;
  422. stream >> topEnd >> leftEnd >> topStart >> leftStart;
  423. stream >> bottom >> right >> top >> left;
  424. xCenter = left + ((right-left) / 2);
  425. yCenter = top + ((bottom-top) / 2);
  426. xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
  427. mReadWmf->drawArc( left, top, right-left, bottom-top, angleStart, aLength);
  428. }
  429. void KoWmfReadPrivate::chord( TQ_UINT32, TQDataStream& stream )
  430. {
  431. int xCenter, yCenter, angleStart, aLength;
  432. TQ_INT16 topEnd, leftEnd, topStart, leftStart;
  433. TQ_INT16 top, left, right, bottom;
  434. stream >> topEnd >> leftEnd >> topStart >> leftStart;
  435. stream >> bottom >> right >> top >> left;
  436. xCenter = left + ((right-left) / 2);
  437. yCenter = top + ((bottom-top) / 2);
  438. xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
  439. mReadWmf->drawChord( left, top, right-left, bottom-top, angleStart, aLength);
  440. }
  441. void KoWmfReadPrivate::pie( TQ_UINT32, TQDataStream& stream )
  442. {
  443. int xCenter, yCenter, angleStart, aLength;
  444. TQ_INT16 topEnd, leftEnd, topStart, leftStart;
  445. TQ_INT16 top, left, right, bottom;
  446. stream >> topEnd >> leftEnd >> topStart >> leftStart;
  447. stream >> bottom >> right >> top >> left;
  448. xCenter = left + ((right-left) / 2);
  449. yCenter = top + ((bottom-top) / 2);
  450. xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
  451. mReadWmf->drawPie( left, top, right-left, bottom-top, angleStart, aLength);
  452. }
  453. void KoWmfReadPrivate::setPolyFillMode( TQ_UINT32, TQDataStream& stream )
  454. {
  455. TQ_UINT16 winding;
  456. stream >> winding;
  457. mWinding = (winding != 0);
  458. }
  459. void KoWmfReadPrivate::setBkColor( TQ_UINT32, TQDataStream& stream )
  460. {
  461. TQ_UINT32 color;
  462. stream >> color;
  463. mReadWmf->setBackgroundColor( qtColor( color ) );
  464. }
  465. void KoWmfReadPrivate::setBkMode( TQ_UINT32, TQDataStream& stream )
  466. {
  467. TQ_UINT16 bkMode;
  468. stream >> bkMode;
  469. if ( bkMode == 1 )
  470. mReadWmf->setBackgroundMode( Qt::TransparentMode );
  471. else
  472. mReadWmf->setBackgroundMode( Qt::OpaqueMode );
  473. }
  474. void KoWmfReadPrivate::setPixel( TQ_UINT32, TQDataStream& stream )
  475. {
  476. TQ_INT16 top, left;
  477. TQ_UINT32 color;
  478. stream >> color >> top >> left;
  479. TQPen oldPen = mReadWmf->pen();
  480. TQPen pen = oldPen;
  481. pen.setColor( qtColor( color ) );
  482. mReadWmf->setPen( pen );
  483. mReadWmf->moveTo( left, top );
  484. mReadWmf->lineTo( left, top );
  485. mReadWmf->setPen( oldPen );
  486. }
  487. void KoWmfReadPrivate::setRop( TQ_UINT32, TQDataStream& stream )
  488. {
  489. TQ_UINT16 rop;
  490. stream >> rop;
  491. mReadWmf->setRasterOp( winToTQtRaster( rop ) );
  492. }
  493. void KoWmfReadPrivate::saveDC( TQ_UINT32, TQDataStream& )
  494. {
  495. mReadWmf->save();
  496. }
  497. void KoWmfReadPrivate::restoreDC( TQ_UINT32, TQDataStream& stream )
  498. {
  499. TQ_INT16 num;
  500. stream >> num;
  501. for ( int i=0; i > num ; i-- )
  502. mReadWmf->restore();
  503. }
  504. void KoWmfReadPrivate::intersectClipRect( TQ_UINT32, TQDataStream& stream )
  505. {
  506. TQ_INT16 top, left, right, bottom;
  507. stream >> bottom >> right >> top >> left;
  508. TQRegion region = mReadWmf->clipRegion();
  509. TQRegion newRegion( left, top, right-left, bottom-top );
  510. if ( region.isEmpty() ) {
  511. region = newRegion;
  512. }
  513. else {
  514. region = region.intersect( newRegion );
  515. }
  516. mReadWmf->setClipRegion( region );
  517. }
  518. void KoWmfReadPrivate::excludeClipRect( TQ_UINT32, TQDataStream& stream )
  519. {
  520. TQ_INT16 top, left, right, bottom;
  521. stream >> bottom >> right >> top >> left;
  522. TQRegion region = mReadWmf->clipRegion();
  523. TQRegion newRegion( left, top, right-left, bottom-top );
  524. if ( region.isEmpty() ) {
  525. region = newRegion;
  526. }
  527. else {
  528. region = region.subtract( newRegion );
  529. }
  530. mReadWmf->setClipRegion( region );
  531. }
  532. //-----------------------------------------------------------------------------
  533. // Text
  534. void KoWmfReadPrivate::setTextColor( TQ_UINT32, TQDataStream& stream )
  535. {
  536. TQ_UINT32 color;
  537. stream >> color;
  538. mTextColor = qtColor( color );
  539. }
  540. void KoWmfReadPrivate::setTextAlign( TQ_UINT32, TQDataStream& stream )
  541. {
  542. stream >> mTextAlign;
  543. }
  544. void KoWmfReadPrivate::textOut( TQ_UINT32, TQDataStream& )
  545. {
  546. if ( mNbrFunc ) {
  547. kdDebug() << "textOut : unimplemented " << endl;
  548. }
  549. }
  550. void KoWmfReadPrivate::extTextOut( TQ_UINT32 , TQDataStream& )
  551. {
  552. if ( mNbrFunc ) {
  553. kdDebug() << "extTextOut : unimplemented " << endl;
  554. }
  555. }
  556. //-----------------------------------------------------------------------------
  557. // Bitmap
  558. void KoWmfReadPrivate::SetStretchBltMode( TQ_UINT32, TQDataStream& )
  559. {
  560. if ( mNbrFunc ) {
  561. kdDebug() << "SetStretchBltMode : unimplemented " << endl;
  562. }
  563. }
  564. void KoWmfReadPrivate::dibBitBlt( TQ_UINT32 size, TQDataStream& stream )
  565. {
  566. TQ_UINT32 raster;
  567. TQ_INT16 topSrc, leftSrc, widthSrc, heightSrc;
  568. TQ_INT16 topDst, leftDst;
  569. stream >> raster;
  570. stream >> topSrc >> leftSrc >> heightSrc >> widthSrc;
  571. stream >> topDst >> leftDst;
  572. if ( size > 11 ) { // DIB image
  573. TQImage bmpSrc;
  574. if ( dibToBmp( bmpSrc, stream, (size - 11) * 2 ) ) {
  575. mReadWmf->setRasterOp( winToTQtRaster( raster ) );
  576. mReadWmf->save();
  577. if ( widthSrc < 0 ) {
  578. // negative width => horizontal flip
  579. TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
  580. mReadWmf->setWorldMatrix( m, true );
  581. }
  582. if ( heightSrc < 0 ) {
  583. // negative height => vertical flip
  584. TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
  585. mReadWmf->setWorldMatrix( m, true );
  586. }
  587. mReadWmf->drawImage( leftDst, topDst, bmpSrc, leftSrc, topSrc, widthSrc, heightSrc );
  588. mReadWmf->restore();
  589. }
  590. }
  591. else {
  592. kdDebug() << "KoWmfReadPrivate::dibBitBlt without image not implemented " << endl;
  593. }
  594. }
  595. void KoWmfReadPrivate::dibStretchBlt( TQ_UINT32 size, TQDataStream& stream )
  596. {
  597. TQ_UINT32 raster;
  598. TQ_INT16 topSrc, leftSrc, widthSrc, heightSrc;
  599. TQ_INT16 topDst, leftDst, widthDst, heightDst;
  600. TQImage bmpSrc;
  601. stream >> raster;
  602. stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
  603. stream >> heightDst >> widthDst >> topDst >> leftDst;
  604. if ( dibToBmp( bmpSrc, stream, (size - 13) * 2 ) ) {
  605. mReadWmf->setRasterOp( winToTQtRaster( raster ) );
  606. mReadWmf->save();
  607. if ( widthDst < 0 ) {
  608. // negative width => horizontal flip
  609. TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
  610. mReadWmf->setWorldMatrix( m, true );
  611. }
  612. if ( heightDst < 0 ) {
  613. // negative height => vertical flip
  614. TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
  615. mReadWmf->setWorldMatrix( m, true );
  616. }
  617. bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
  618. // TODO: scale the bitmap : TQImage::scale(widthDst, heightDst)
  619. // is actually too slow
  620. mReadWmf->drawImage( leftDst, topDst, bmpSrc );
  621. mReadWmf->restore();
  622. }
  623. }
  624. void KoWmfReadPrivate::stretchDib( TQ_UINT32 size, TQDataStream& stream )
  625. {
  626. TQ_UINT32 raster;
  627. TQ_INT16 arg, topSrc, leftSrc, widthSrc, heightSrc;
  628. TQ_INT16 topDst, leftDst, widthDst, heightDst;
  629. TQImage bmpSrc;
  630. stream >> raster >> arg;
  631. stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
  632. stream >> heightDst >> widthDst >> topDst >> leftDst;
  633. if ( dibToBmp( bmpSrc, stream, (size - 14) * 2 ) ) {
  634. mReadWmf->setRasterOp( winToTQtRaster( raster ) );
  635. mReadWmf->save();
  636. if ( widthDst < 0 ) {
  637. // negative width => horizontal flip
  638. TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
  639. mReadWmf->setWorldMatrix( m, true );
  640. }
  641. if ( heightDst < 0 ) {
  642. // negative height => vertical flip
  643. TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
  644. mReadWmf->setWorldMatrix( m, true );
  645. }
  646. bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
  647. // TODO: scale the bitmap ( TQImage::scale(param[ 8 ], param[ 7 ]) is actually too slow )
  648. mReadWmf->drawImage( leftDst, topDst, bmpSrc );
  649. mReadWmf->restore();
  650. }
  651. }
  652. void KoWmfReadPrivate::dibCreatePatternBrush( TQ_UINT32 size, TQDataStream& stream )
  653. {
  654. KoWmfPatternBrushHandle* handle = new KoWmfPatternBrushHandle;
  655. if ( addHandle( handle ) ) {
  656. TQ_UINT32 arg;
  657. TQImage bmpSrc;
  658. stream >> arg;
  659. if ( dibToBmp( bmpSrc, stream, (size - 5) * 2 ) ) {
  660. handle->image = bmpSrc;
  661. handle->brush.setPixmap( handle->image );
  662. }
  663. else {
  664. kdDebug() << "KoWmfReadPrivate::dibCreatePatternBrush : incorrect DIB image" << endl;
  665. }
  666. }
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Object handle
  670. void KoWmfReadPrivate::selectObject( TQ_UINT32, TQDataStream& stream )
  671. {
  672. TQ_UINT16 idx;
  673. stream >> idx;
  674. if ( (idx < mNbrObject) && (mObjHandleTab[ idx ] != 0) )
  675. mObjHandleTab[ idx ]->apply( mReadWmf );
  676. else
  677. kdDebug() << "KoWmfReadPrivate::selectObject : selection of an empty object" << endl;
  678. }
  679. void KoWmfReadPrivate::deleteObject( TQ_UINT32, TQDataStream& stream )
  680. {
  681. TQ_UINT16 idx;
  682. stream >> idx;
  683. deleteHandle( idx );
  684. }
  685. void KoWmfReadPrivate::createEmptyObject()
  686. {
  687. // allocation of an empty object (to keep object counting in sync)
  688. KoWmfPenHandle* handle = new KoWmfPenHandle;
  689. addHandle( handle );
  690. }
  691. void KoWmfReadPrivate::createBrushIndirect( TQ_UINT32, TQDataStream& stream )
  692. {
  693. Qt::BrushStyle style;
  694. TQ_UINT16 sty, arg2;
  695. TQ_UINT32 color;
  696. KoWmfBrushHandle* handle = new KoWmfBrushHandle;
  697. if ( addHandle( handle ) ) {
  698. stream >> sty >> color >> arg2;
  699. if ( sty == 2 ) {
  700. if ( arg2 < 6 )
  701. style = koWmfHatchedStyleBrush[ arg2 ];
  702. else
  703. {
  704. kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid hatched brush " << arg2 << endl;
  705. style = Qt::SolidPattern;
  706. }
  707. }
  708. else {
  709. if ( sty < 9 )
  710. style = koWmfStyleBrush[ sty ];
  711. else {
  712. kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid brush " << sty << endl;
  713. style = Qt::SolidPattern;
  714. }
  715. }
  716. handle->brush.setStyle( style );
  717. handle->brush.setColor( qtColor( color ) );
  718. }
  719. }
  720. void KoWmfReadPrivate::createPenIndirect( TQ_UINT32, TQDataStream& stream )
  721. {
  722. // TODO: userStyle and alternateStyle
  723. Qt::PenStyle penStyle;
  724. TQ_UINT32 color;
  725. TQ_UINT16 style, width, arg;
  726. KoWmfPenHandle* handle = new KoWmfPenHandle;
  727. if ( addHandle( handle ) ) {
  728. stream >> style >> width >> arg >> color;
  729. if ( style < 7 )
  730. penStyle=koWmfStylePen[ style ];
  731. else {
  732. kdDebug() << "KoWmfReadPrivate::createPenIndirect: invalid pen " << style << endl;
  733. penStyle = Qt::SolidLine;
  734. }
  735. handle->pen.setStyle( penStyle );
  736. handle->pen.setColor( qtColor( color ) );
  737. handle->pen.setCapStyle( Qt::RoundCap );
  738. handle->pen.setWidth( width );
  739. }
  740. }
  741. void KoWmfReadPrivate::createFontIndirect( TQ_UINT32 size, TQDataStream& stream )
  742. {
  743. TQ_INT16 pointSize, rotation;
  744. TQ_UINT16 weight, property, fixedPitch, arg;
  745. KoWmfFontHandle* handle = new KoWmfFontHandle;
  746. if ( addHandle( handle ) ) {
  747. stream >> pointSize >> arg;
  748. stream >> rotation >> arg;
  749. stream >> weight >> property >> arg >> arg;
  750. stream >> fixedPitch;
  751. // text rotation (in 1/10 degree)
  752. // TODO: memorisation of rotation in object Font
  753. mTextRotation = -rotation / 10;
  754. handle->font.setFixedPitch( ((fixedPitch & 0x01) == 0) );
  755. // TODO: investigation why some test case need -2
  756. // size of font in logical point
  757. handle->font.setPointSize( TQABS(pointSize) - 2 );
  758. handle->font.setWeight( (weight >> 3) );
  759. handle->font.setItalic( (property & 0x01) );
  760. handle->font.setUnderline( (property & 0x100) );
  761. // font name
  762. int maxChar = (size-12) * 2;
  763. char* nameFont = new char[maxChar];
  764. stream.readRawBytes( nameFont, maxChar );
  765. handle->font.setFamily( nameFont );
  766. delete[] nameFont;
  767. }
  768. }
  769. //-----------------------------------------------------------------------------
  770. // Misc functions
  771. void KoWmfReadPrivate::end( TQ_UINT32, TQDataStream& )
  772. {
  773. }
  774. TQ_UINT16 KoWmfReadPrivate::calcCheckSum( WmfPlaceableHeader* apmfh )
  775. {
  776. TQ_UINT16* lpWord;
  777. TQ_UINT16 wResult, i;
  778. // Start with the first word
  779. wResult = *( lpWord = ( TQ_UINT16* )( apmfh ) );
  780. // XOR in each of the other 9 words
  781. for( i=1; i<=9; i++ )
  782. {
  783. wResult ^= lpWord[ i ];
  784. }
  785. return wResult;
  786. }
  787. void KoWmfReadPrivate::notyet( TQ_UINT32, TQDataStream& )
  788. {
  789. if ( mNbrFunc ) {
  790. kdDebug() << "unimplemented " << endl;
  791. }
  792. }
  793. void KoWmfReadPrivate::region( TQ_UINT32, TQDataStream& )
  794. {
  795. if ( mNbrFunc ) {
  796. kdDebug() << "region : unimplemented " << endl;
  797. }
  798. }
  799. void KoWmfReadPrivate::palette( TQ_UINT32, TQDataStream& )
  800. {
  801. if ( mNbrFunc ) {
  802. kdDebug() << "palette : unimplemented " << endl;
  803. }
  804. }
  805. void KoWmfReadPrivate::escape( TQ_UINT32, TQDataStream& )
  806. {
  807. if ( mNbrFunc ) {
  808. kdDebug() << "escape : unimplemented " << endl;
  809. }
  810. }
  811. void KoWmfReadPrivate::setRelAbs( TQ_UINT32, TQDataStream& )
  812. {
  813. if ( mNbrFunc ) {
  814. kdDebug() << "setRelAbs : unimplemented " << endl;
  815. }
  816. }
  817. void KoWmfReadPrivate::setMapMode( TQ_UINT32, TQDataStream& )
  818. {
  819. if ( mNbrFunc ) {
  820. kdDebug() << "setMapMode : unimplemented " << endl;
  821. }
  822. }
  823. void KoWmfReadPrivate::extFloodFill( TQ_UINT32, TQDataStream& )
  824. {
  825. if ( mNbrFunc ) {
  826. kdDebug() << "extFloodFill : unimplemented " << endl;
  827. }
  828. }
  829. void KoWmfReadPrivate::startDoc( TQ_UINT32, TQDataStream& )
  830. {
  831. if ( mNbrFunc ) {
  832. kdDebug() << "startDoc : unimplemented " << endl;
  833. }
  834. }
  835. void KoWmfReadPrivate::startPage( TQ_UINT32, TQDataStream& )
  836. {
  837. if ( mNbrFunc ) {
  838. kdDebug() << "startPage : unimplemented " << endl;
  839. }
  840. }
  841. void KoWmfReadPrivate::endDoc( TQ_UINT32, TQDataStream& )
  842. {
  843. if ( mNbrFunc ) {
  844. kdDebug() << "endDoc : unimplemented " << endl;
  845. }
  846. }
  847. void KoWmfReadPrivate::endPage( TQ_UINT32, TQDataStream& )
  848. {
  849. if ( mNbrFunc ) {
  850. kdDebug() << "endPage : unimplemented " << endl;
  851. }
  852. }
  853. void KoWmfReadPrivate::resetDC( TQ_UINT32, TQDataStream& )
  854. {
  855. if ( mNbrFunc ) {
  856. kdDebug() << "resetDC : unimplemented " << endl;
  857. }
  858. }
  859. void KoWmfReadPrivate::bitBlt( TQ_UINT32, TQDataStream& )
  860. {
  861. if ( mNbrFunc ) {
  862. kdDebug() << "bitBlt : unimplemented " << endl;
  863. }
  864. }
  865. void KoWmfReadPrivate::setDibToDev( TQ_UINT32, TQDataStream& )
  866. {
  867. if ( mNbrFunc ) {
  868. kdDebug() << "setDibToDev : unimplemented " << endl;
  869. }
  870. }
  871. void KoWmfReadPrivate::createBrush( TQ_UINT32, TQDataStream& )
  872. {
  873. if ( mNbrFunc ) {
  874. kdDebug() << "createBrush : unimplemented " << endl;
  875. }
  876. }
  877. void KoWmfReadPrivate::createPatternBrush( TQ_UINT32, TQDataStream& )
  878. {
  879. if ( mNbrFunc ) {
  880. kdDebug() << "createPatternBrush : unimplemented " << endl;
  881. }
  882. }
  883. void KoWmfReadPrivate::createBitmap( TQ_UINT32, TQDataStream& )
  884. {
  885. if ( mNbrFunc ) {
  886. kdDebug() << "createBitmap : unimplemented " << endl;
  887. }
  888. }
  889. void KoWmfReadPrivate::createBitmapIndirect( TQ_UINT32, TQDataStream& )
  890. {
  891. createEmptyObject();
  892. if ( mNbrFunc ) {
  893. kdDebug() << "createBitmapIndirect : unimplemented " << endl;
  894. }
  895. }
  896. void KoWmfReadPrivate::createPalette( TQ_UINT32, TQDataStream& )
  897. {
  898. createEmptyObject();
  899. if ( mNbrFunc ) {
  900. kdDebug() << "createPalette : unimplemented " << endl;
  901. }
  902. }
  903. void KoWmfReadPrivate::createRegion( TQ_UINT32, TQDataStream& )
  904. {
  905. createEmptyObject();
  906. if ( mNbrFunc ) {
  907. kdDebug() << "createRegion : unimplemented " << endl;
  908. }
  909. }
  910. //-----------------------------------------------------------------------------
  911. // Utilities and conversion Wmf -> TQt
  912. bool KoWmfReadPrivate::addHandle( KoWmfHandle* handle )
  913. {
  914. int idx;
  915. for ( idx=0; idx < mNbrObject ; idx++ ) {
  916. if ( mObjHandleTab[ idx ] == 0 ) break;
  917. }
  918. if ( idx < mNbrObject ) {
  919. mObjHandleTab[ idx ] = handle;
  920. return true;
  921. }
  922. else {
  923. delete handle;
  924. mStackOverflow = true;
  925. kdDebug() << "KoWmfReadPrivate::addHandle : stack overflow = broken file !" << endl;
  926. return false;
  927. }
  928. }
  929. void KoWmfReadPrivate::deleteHandle( int idx )
  930. {
  931. if ( (idx < mNbrObject) && (mObjHandleTab[idx] != 0) ) {
  932. delete mObjHandleTab[ idx ];
  933. mObjHandleTab[ idx ] = 0;
  934. }
  935. else {
  936. kdDebug() << "KoWmfReadPrivate::deletehandle() : bad index number" << endl;
  937. }
  938. }
  939. void KoWmfReadPrivate::pointArray( TQDataStream& stream, TQPointArray& pa )
  940. {
  941. TQ_INT16 left, top;
  942. int i, max;
  943. for ( i=0, max=pa.size() ; i < max ; i++ ) {
  944. stream >> left >> top;
  945. pa.setPoint( i, left, top );
  946. }
  947. }
  948. void KoWmfReadPrivate::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
  949. {
  950. double aStart, aLength;
  951. aStart = atan2( yStart, xStart );
  952. aLength = atan2( yEnd, xEnd ) - aStart;
  953. angleStart = (int)((aStart * 2880) / 3.14166);
  954. angleLength = (int)((aLength * 2880) / 3.14166);
  955. if ( angleLength < 0 ) angleLength = 5760 + angleLength;
  956. }
  957. TQt::RasterOp KoWmfReadPrivate::winToTQtRaster( TQ_UINT16 param ) const
  958. {
  959. if ( param < 17 )
  960. return koWmfOpTab16[ param ];
  961. else
  962. return TQt::CopyROP;
  963. }
  964. TQt::RasterOp KoWmfReadPrivate::winToTQtRaster( TQ_UINT32 param ) const
  965. {
  966. /* TODO: Ternary raster operations
  967. 0x00C000CA dest = (source AND pattern)
  968. 0x00F00021 dest = pattern
  969. 0x00FB0A09 dest = DPSnoo
  970. 0x005A0049 dest = pattern XOR dest */
  971. int i;
  972. for ( i=0 ; i < 15 ; i++ ) {
  973. if ( koWmfOpTab32[ i ].winRasterOp == param ) break;
  974. }
  975. if ( i < 15 )
  976. return koWmfOpTab32[ i ].qtRasterOp;
  977. else
  978. return TQt::CopyROP;
  979. }
  980. bool KoWmfReadPrivate::dibToBmp( TQImage& bmp, TQDataStream& stream, TQ_UINT32 size )
  981. {
  982. typedef struct _BMPFILEHEADER {
  983. TQ_UINT16 bmType;
  984. TQ_UINT32 bmSize;
  985. TQ_UINT16 bmReserved1;
  986. TQ_UINT16 bmReserved2;
  987. TQ_UINT32 bmOffBits;
  988. } BMPFILEHEADER;
  989. int sizeBmp = size + 14;
  990. TQByteArray pattern( sizeBmp ); // BMP header and DIB data
  991. pattern.fill(0);
  992. stream.readRawBytes( &pattern[ 14 ], size );
  993. // add BMP header
  994. BMPFILEHEADER* bmpHeader;
  995. bmpHeader = (BMPFILEHEADER*)(pattern.data());
  996. bmpHeader->bmType = 0x4D42;
  997. bmpHeader->bmSize = sizeBmp;
  998. // if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
  999. if ( !bmp.loadFromData( pattern, "BMP" ) ) {
  1000. kdDebug() << "KoWmfReadPrivate::dibToBmp: invalid bitmap " << endl;
  1001. return false;
  1002. }
  1003. else {
  1004. return true;
  1005. }
  1006. }