21
22
#include <QPolygon>
22
23
#include <QPrinter>
24
#include <QFontMetrics>
24
26
#include <kdebug.h>
26
KoWmfPaint::KoWmfPaint() : KoWmfRead() {
28
#include "kowmfenums.h"
31
KoWmfPaint::KoWmfPaint()
36
mIsInternalPainter = true;
31
bool KoWmfPaint::play( QPaintDevice& target, bool relativeCoord )
41
bool KoWmfPaint::play(QPaintDevice& target, bool relativeCoord)
33
if ( mPainter.isActive() ) return false;
44
mPainter = new QPainter(&target);
45
mIsInternalPainter = true;
47
if (mPainter->isActive()) return false;
35
49
mRelativeCoord = relativeCoord;
37
51
// Play the wmf file
38
return KoWmfRead::play( );
52
return KoWmfRead::play();
55
bool KoWmfPaint::play(QPainter &painter, bool relativeCoord)
57
// If there is already a painter and it's owned by us, then delete i
58
if (mPainter && mIsInternalPainter)
61
// Set the new painter
62
mIsInternalPainter = false;
65
mTarget = mPainter->device();
66
mRelativeCoord = relativeCoord;
69
return KoWmfRead::play();
42
73
//-----------------------------------------------------------------------------
45
bool KoWmfPaint::begin() {
46
bool ret = mPainter.begin( mTarget );
49
if ( mRelativeCoord ) {
76
bool KoWmfPaint::begin()
80
// If the painter is our own, we have to call begin() on it.
81
// If it's external, we suppose that it's already done for us.
82
if (mIsInternalPainter)
83
ret = mPainter->begin(mTarget);
50
87
mInternalWorldMatrix.reset();
53
// some wmf files doesn't call setwindowOrg and setWindowExt, so it's better to do :
89
// This window is used for scaling in setWindowExt().
90
mPainter->setWindow(boundingRect());
92
// Some WMF files don't call setwindowOrg and
93
// setWindowExt, so it's better to do it here. Note that
94
// boundingRect() is the rect of the WMF file, not the device.
54
95
QRect rec = boundingRect();
55
mPainter.setWindow( rec.left(), rec.top(), rec.width(), rec.height() );
96
//kDebug(31000) << "BoundingRect: " << rec;
97
mPainter->setWindow(rec);
62
bool KoWmfPaint::end() {
63
if ( mRelativeCoord ) {
64
QRect rec = boundingRect();
66
// Draw 2 invisible points
67
// because QPicture::setBoundingRect() doesn't give expected result (QT3.1.2)
68
// setBoundingRect( boundingRect() );
69
// mPainter.setPen( Qt::NoPen );
70
// mPainter.drawPoint( rec.left(), rec.top() );
71
// mPainter.drawPoint( rec.right(), rec.bottom() );
73
return mPainter.end();
77
void KoWmfPaint::save() {
82
void KoWmfPaint::restore() {
87
void KoWmfPaint::setFont( const QFont &font ) {
88
mPainter.setFont( font );
92
void KoWmfPaint::setPen( const QPen &pen ) {
102
kDebug(31000) << "Using QPainter: " << mPainter->pen() << mPainter->brush()
103
<< "Background: " << mPainter->background() << " " << mPainter->backgroundMode();
104
kDebug(31000) << "KoWmfPaint::begin returns " << ret;
111
bool KoWmfPaint::end()
114
if (mIsInternalPainter)
115
ret = mPainter->end();
121
void KoWmfPaint::save()
127
void KoWmfPaint::restore()
133
void KoWmfPaint::setFont(const QFont &font)
136
kDebug(31000) << font;
138
mPainter->setFont(font);
142
void KoWmfPaint::setTextPen(const QPen &pen)
145
kDebug(31000) << pen;
151
void KoWmfPaint::setPen(const QPen &pen)
154
kDebug(31000) << pen;
94
158
int width = pen.width();
96
if ( dynamic_cast<QPrinter *>( mTarget ) ) {
160
if (dynamic_cast<QPrinter *>(mTarget)) {
100
// WMF spec : width of pen in logical coordinate
163
// WMF spec: width of pen in logical coordinate
101
164
// => width of pen proportional with device context width
102
QRect rec = mPainter.window();
165
QRect rec = mPainter->window();
103
166
// QPainter documentation says this is equivalent of xFormDev, but it doesn't compile. Bug reported.
105
QRect devRec = rec * mPainter.matrix();
106
if ( rec.width() != 0 )
107
width = ( width * devRec.width() ) / rec.width() ;
168
QRect devRec = rec * mPainter->matrix();
169
if (rec.width() != 0)
170
width = (width * devRec.width()) / rec.width() ;
114
mPainter.setPen( p );
118
const QPen &KoWmfPaint::pen() const {
119
return mPainter.pen();
123
void KoWmfPaint::setBrush( const QBrush &brush ) {
124
mPainter.setBrush( brush );
128
void KoWmfPaint::setBackgroundColor( const QColor &c ) {
129
mPainter.setBackground( QBrush( c ) );
133
void KoWmfPaint::setBackgroundMode( Qt::BGMode mode ) {
134
mPainter.setBackgroundMode( mode );
138
void KoWmfPaint::setCompositionMode( QPainter::CompositionMode mode ) {
139
mPainter.setCompositionMode( mode );
181
const QPen &KoWmfPaint::pen() const
183
return mPainter->pen();
187
void KoWmfPaint::setBrush(const QBrush &brush)
190
kDebug(31000) << brush;
192
mPainter->setBrush(brush);
196
void KoWmfPaint::setBackgroundColor(const QColor &c)
201
// FIXME: This needs more investigation, but it seems that the
202
// concept of "background" in WMF is the same as the
203
// "brush" in QPainter.
204
// Update: No, it wasn't. I changed back now because it didn't work. I'm leaving
205
// the fixme and this comment to remind the next fixer that calling
206
// setBrush() is not the solution. I hope nothing breaks now.
207
// The date is now 2010-01-20. If nothing breaks in a couple of months,
208
// all this commentry can be removed.
209
//mPainter->setBrush(QBrush(c));
210
mPainter->setBackground(QBrush(c));
214
void KoWmfPaint::setBackgroundMode(Qt::BGMode mode)
217
kDebug(31000) << mode << "(ignored)";
220
mPainter->setBackgroundMode(mode);
224
void KoWmfPaint::setCompositionMode(QPainter::CompositionMode mode)
227
kDebug(31000) << mode << "(ignored)";
230
// FIXME: This doesn't work. I don't understand why, but when I
231
// enable this all backgrounds become black. /iw
233
//mPainter->setCompositionMode(mode);
147
241
// - change the origin or the scale in the middle of the drawing
148
242
// - negative width or height
149
243
// and relative/absolute coordinate
150
void KoWmfPaint::setWindowOrg( int left, int top ) {
151
if ( mRelativeCoord ) {
152
double dx = mInternalWorldMatrix.dx();
153
double dy = mInternalWorldMatrix.dy();
155
// translation : Don't use setWindow()
156
mInternalWorldMatrix.translate( -dx, -dy );
157
mPainter.translate( -dx, -dy );
158
mInternalWorldMatrix.translate( -left, -top );
159
mPainter.translate( -left, -top );
162
QRect rec = mPainter.window();
163
mPainter.setWindow( left, top, rec.width(), rec.height() );
168
void KoWmfPaint::setWindowExt( int w, int h ) {
169
if ( mRelativeCoord ) {
170
QRect r = mPainter.window();
171
double dx = mInternalWorldMatrix.dx();
172
double dy = mInternalWorldMatrix.dy();
173
double sx = mInternalWorldMatrix.m11();
174
double sy = mInternalWorldMatrix.m22();
176
// scale : don't use setWindow()
177
mInternalWorldMatrix.translate( -dx, -dy );
178
mPainter.translate( -dx, -dy );
179
mInternalWorldMatrix.scale( 1/sx, 1/sy );
180
mPainter.scale( 1/sx, 1/sy );
182
sx = (double)r.width() / (double)w;
183
sy = (double)r.height() / (double)h;
185
mInternalWorldMatrix.scale( sx, sy );
186
mPainter.scale( sx, sy );
187
mInternalWorldMatrix.translate( dx, dy );
188
mPainter.translate( dx, dy );
191
QRect rec = mPainter.window();
192
mPainter.setWindow( rec.left(), rec.top(), w, h );
197
void KoWmfPaint::setMatrix( const QMatrix &wm, bool combine ) {
198
mPainter.setMatrix( wm, combine );
202
void KoWmfPaint::setClipRegion( const QRegion &rec ) {
203
mPainter.setClipRegion( rec );
207
QRegion KoWmfPaint::clipRegion() {
208
return mPainter.clipRegion();
212
void KoWmfPaint::moveTo( int x, int y ) {
213
mLastPos = QPoint( x, y );
217
void KoWmfPaint::lineTo( int x, int y ) {
218
mPainter.drawLine( mLastPos, QPoint( x, y ) );
222
void KoWmfPaint::drawRect( int x, int y, int w, int h ) {
223
mPainter.drawRect( x, y, w, h );
227
void KoWmfPaint::drawRoundRect( int x, int y, int w, int h, int roudw, int roudh ) {
228
mPainter.drawRoundRect( x, y, w, h, roudw, roudh );
232
void KoWmfPaint::drawEllipse( int x, int y, int w, int h ) {
233
mPainter.drawEllipse( x, y, w, h );
237
void KoWmfPaint::drawArc( int x, int y, int w, int h, int a, int alen ) {
238
mPainter.drawArc( x, y, w, h, a, alen );
242
void KoWmfPaint::drawPie( int x, int y, int w, int h, int a, int alen ) {
243
mPainter.drawPie( x, y, w, h, a, alen );
247
void KoWmfPaint::drawChord( int x, int y, int w, int h, int a, int alen ) {
248
mPainter.drawChord( x, y, w, h, a, alen );
252
void KoWmfPaint::drawPolyline( const QPolygon &pa ) {
253
mPainter.drawPolyline( pa );
257
void KoWmfPaint::drawPolygon( const QPolygon &pa, bool winding ) {
259
mPainter.drawPolygon( pa, Qt::WindingFill );
245
void KoWmfPaint::setWindowOrg(int orgX, int orgY) // Love that parameter name...
248
kDebug(31000) << orgX << " " << orgY;
254
if (mRelativeCoord) {
255
// Translate back from last translation to the origin.
256
qreal dx = mInternalWorldMatrix.dx();
257
qreal dy = mInternalWorldMatrix.dy();
258
//kDebug(31000) << "old translation: " << dx << dy;
259
//kDebug(31000) << mInternalWorldMatrix;
260
//kDebug(31000) << "new translation: " << -orgX << -orgY;
261
mInternalWorldMatrix.translate(-dx, -dy);
262
mPainter->translate(-dx, -dy);
264
// Translate to the new origin.
265
mInternalWorldMatrix.translate(-orgX, -orgY);
266
mPainter->translate(-orgX, -orgY);
268
QRect rec = mPainter->window();
269
mPainter->setWindow(orgX, orgY, rec.width(), rec.height());
274
void KoWmfPaint::setWindowExt(int width, int height)
277
kDebug(31000) << width << " " << height;
283
if (mRelativeCoord) {
284
QRect r = mPainter->window();
285
qreal dx = mInternalWorldMatrix.dx();
286
qreal dy = mInternalWorldMatrix.dy();
287
qreal sx = mInternalWorldMatrix.m11();
288
qreal sy = mInternalWorldMatrix.m22();
290
// Translate and scale back from the last window.
291
mInternalWorldMatrix.translate(-dx, -dy);
292
mPainter->translate(-dx, -dy);
293
mInternalWorldMatrix.scale(1 / sx, 1 / sy);
294
mPainter->scale(1 / sx, 1 / sy);
296
sx = (qreal)r.width() / (qreal)width;
297
sy = (qreal)r.height() / (qreal)height;
299
// Scale and translate into the new window
300
mInternalWorldMatrix.scale(sx, sy);
301
mPainter->scale(sx, sy);
302
mInternalWorldMatrix.translate(dx, dy);
303
mPainter->translate(dx, dy);
305
QRect rec = mPainter->window();
306
mPainter->setWindow(rec.left(), rec.top(), width, height);
310
mPainter->setPen(Qt::black);
311
mPainter->drawRect(QRect(QPoint(mOrgX, mOrgY),
312
QSize(mExtWidth, mExtHeight)));
313
mPainter->setPen(Qt::red);
314
mPainter->drawRect(boundingRect());
320
void KoWmfPaint::setMatrix(const QMatrix &wm, bool combine)
323
kDebug(31000) << wm << " " << combine;
325
mPainter->setMatrix(wm, combine);
329
void KoWmfPaint::setClipRegion(const QRegion &rec)
331
mPainter->setClipRegion(rec);
335
QRegion KoWmfPaint::clipRegion()
337
return mPainter->clipRegion();
341
void KoWmfPaint::moveTo(int x, int y)
344
kDebug(31000)<< x << ", " << y;
346
mLastPos = QPoint(x, y);
350
void KoWmfPaint::lineTo(int x, int y)
353
kDebug(31000) << x << ", " << y << " using " << mPainter->pen()
354
<< "linewidth: " << mPainter->pen().width();
357
QPoint newPoint(x, y);
358
mPainter->drawLine(mLastPos, newPoint);
363
void KoWmfPaint::drawRect(int x, int y, int w, int h)
366
kDebug(31000) << x << ", " << y << ", " << w << ", " << h;
367
kDebug(31000) << "Using QPainter: " << mPainter->pen() << mPainter->brush();
370
mPainter->drawRect(x, y, w, h);
374
void KoWmfPaint::drawRoundRect(int x, int y, int w, int h, int roudw, int roudh)
377
kDebug(31000) << x << ", " << y << ", " << w << ", " << h;
379
mPainter->drawRoundRect(x, y, w, h, roudw, roudh);
383
void KoWmfPaint::drawEllipse(int x, int y, int w, int h)
386
kDebug(31000) << x << ", " << y << ", " << w << ", " << h;
388
mPainter->drawEllipse(x, y, w, h);
392
void KoWmfPaint::drawArc(int x, int y, int w, int h, int a, int alen)
395
kDebug(31000) << x << ", " << y << ", " << w << ", " << h;
397
mPainter->drawArc(x, y, w, h, a, alen);
401
void KoWmfPaint::drawPie(int x, int y, int w, int h, int a, int alen)
404
kDebug(31000) << x << ", " << y << ", " << w << ", " << h;
406
mPainter->drawPie(x, y, w, h, a, alen);
410
void KoWmfPaint::drawChord(int x, int y, int w, int h, int a, int alen)
413
kDebug(31000) << x << ", " << y << ", " << w << ", " << h
414
<< ", " << a << ", " << alen;
416
mPainter->drawChord(x, y, w, h, a, alen);
420
void KoWmfPaint::drawPolyline(const QPolygon &pa)
425
mPainter->drawPolyline(pa);
429
void KoWmfPaint::drawPolygon(const QPolygon &pa, bool winding)
432
kDebug(31000) << pa << winding;
433
kDebug(31000) << "Using QPainter: " << mPainter->pen() << mPainter->brush();
437
mPainter->drawPolygon(pa, Qt::WindingFill);
261
mPainter.drawPolygon( pa, Qt::OddEvenFill );
439
mPainter->drawPolygon(pa, Qt::OddEvenFill);
265
void KoWmfPaint::drawPolyPolygon( QList<QPolygon>& listPa, bool winding ) {
267
QBrush brush = mPainter.brush();
443
void KoWmfPaint::drawPolyPolygon(QList<QPolygon>& listPa, bool winding)
450
QBrush brush = mPainter->brush();
269
452
// define clipping region
271
foreach ( const QPolygon & pa, listPa ) {
272
region = region.xored( pa );
454
foreach(const QPolygon & pa, listPa) {
455
region = region.xored(pa);
274
mPainter.setClipRegion( region );
457
mPainter->setClipRegion(region);
277
if ( brush != Qt::NoBrush ) {
278
mPainter.fillRect( region.boundingRect(), brush );
460
if (brush != Qt::NoBrush) {
461
kDebug(31000) << "Filling polygon with " << brush;
462
mPainter->fillRect(region.boundingRect(), brush);
281
465
// draw polygon's border
282
mPainter.setClipping( false );
283
if ( mPainter.pen().style() != Qt::NoPen ) {
284
mPainter.setBrush( Qt::NoBrush );
285
foreach ( const QPolygon & pa, listPa )
288
mPainter.drawPolygon( pa, Qt::WindingFill );
466
mPainter->setClipping(false);
467
if (mPainter->pen().style() != Qt::NoPen) {
468
mPainter->setBrush(Qt::NoBrush);
469
foreach(const QPolygon & pa, listPa) {
474
mPainter->drawPolygon(pa, Qt::WindingFill);
290
mPainter.drawPolygon( pa, Qt::OddEvenFill );
476
mPainter->drawPolygon(pa, Qt::OddEvenFill);
294
480
// restore previous state
299
void KoWmfPaint::drawImage( int x, int y, const QImage &img, int sx, int sy, int sw, int sh ) {
300
mPainter.drawImage( x, y, img, sx, sy, sw, sh );
304
void KoWmfPaint::drawText( int x, int y, int w, int h, int flags, const QString& s, double ) {
305
mPainter.drawText( x, y, w, h, flags, s );
485
void KoWmfPaint::drawImage(int x, int y, const QImage &img, int sx, int sy, int sw, int sh)
488
kDebug(31000) << x << " " << y << " " << sx << " " << sy << " " << sw << " " << sh;
490
mPainter->drawImage(x, y, img, sx, sy, sw, sh);
494
void KoWmfPaint::patBlt(int x, int y, int width, int height, quint32 rasterOperation)
497
kDebug(31000) << x << y << width << height << hex << rasterOperation << dec;
500
// 0x00f00021 is the PatCopy raster operation which just fills a rectangle with a brush.
501
// This seems to be the most common one.
503
// FIXME: Implement the rest of the raster operations.
504
if (rasterOperation == 0x00f00021) {
505
// Would have been nice if we didn't have to pull out the
506
// brush to use it with fillRect()...
507
QBrush brush = mPainter->brush();
508
mPainter->fillRect(x, y, width, height, brush);
513
void KoWmfPaint::drawText(int x, int y, int w, int h, int textAlign, const QString& text, double)
516
kDebug(31000) << x << y << w << h << hex << textAlign << dec << text;
519
// The TA_UPDATECP flag tells us to use the current position
520
if (textAlign & TA_UPDATECP) {
521
// (left, top) position = current logical position
526
QFontMetrics fm(mPainter->font(), mTarget);
527
int width = fm.width(text) + fm.descent(); // fm.width(text) isn't right with Italic text
528
int height = fm.height();
530
// Horizontal align. These flags are supposed to be mutually exclusive.
531
if ((textAlign & TA_CENTER) == TA_CENTER)
533
else if ((textAlign & TA_RIGHT) == TA_RIGHT)
537
if ((textAlign & TA_BASELINE) == TA_BASELINE)
538
y -= fm.ascent(); // (height - fm.descent()) is used in qwmf. This should be the same.
539
else if ((textAlign & TA_BOTTOM) == TA_BOTTOM) {
543
kDebug(31000) << "font = " << mPainter->font() << " pointSize = " << mPainter->font().pointSize()
544
<< "ascent = " << fm.ascent() << " height = " << fm.height()
545
<< "leading = " << fm.leading();
549
// Use the special pen defined by mTextPen for text.
550
QPen savePen = mPainter->pen();
551
mPainter->setPen(mTextPen);
553
// Sometimes it happens that w and/or h == -1, and then the bounding box
554
// isn't valid any more. In that case, use our own calculated values.
555
if (w == -1 || h == -1) {
556
mPainter->drawText(x, y, width, height, Qt::AlignLeft|Qt::AlignTop, text);
559
mPainter->drawText(x, y, w, h, Qt::AlignLeft|Qt::AlignTop, text);
562
mPainter->setPen(savePen);