Subversion Repositories Scribus

Rev

Rev 10932 | Rev 10966 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
10928 fschmid 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
/**************************************************************************
8
*   Copyright (C) 2007 by Franz Schmid                                    *
9
*   franz.schmid@altmuehlnet.de                                           *
10
*                                                                         *
11
*   This program is free software; you can redistribute it and/or modify  *
12
*   it under the terms of the GNU General Public License as published by  *
13
*   the Free Software Foundation; either version 2 of the License, or     *
14
*   (at your option) any later version.                                   *
15
*                                                                         *
16
*   This program is distributed in the hope that it will be useful,       *
17
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19
*   GNU General Public License for more details.                          *
20
*                                                                         *
21
*   You should have received a copy of the GNU General Public License     *
22
*   along with this program; if not, write to the                         *
23
*   Free Software Foundation, Inc.,                                       *
24
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25
***************************************************************************/
26
 
27
#include "lensdialog.h"
28
#include <QRadialGradient>
29
#include "util_icon.h"
30
#include "selection.h"
31
#include "sccolorengine.h"
10936 fschmid 32
#include "scpattern.h"
10928 fschmid 33
#include "commonstrings.h"
34
 
35
LensItem::LensItem(QRectF geom, LensDialog *parent) : QGraphicsEllipseItem(geom)
36
{
37
        dialog = parent;
38
        strength = 100.0;
39
        setPen(QPen(Qt::black));
40
        QRadialGradient radialGrad(QPointF(0.5, 0.5), 1.0);
41
        radialGrad.setColorAt(0.0, QColor(255, 0, 0, 127));
42
        radialGrad.setColorAt(0.1, QColor(255, 0, 0, 127));
43
        radialGrad.setColorAt(1.0, QColor(255, 255, 255, 0));
44
#if QT_VERSION  >= 0x040301
45
        radialGrad.setCoordinateMode(QGradient::ObjectBoundingMode);
46
#endif
47
        setBrush(radialGrad);
48
        setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
49
}
50
 
51
void LensItem::setStrength(double s)
52
{
53
        strength = s;
54
}
55
 
56
QVariant LensItem::itemChange(GraphicsItemChange change, const QVariant &value)
57
{
58
        switch (change)
59
        {
60
                case ItemSelectedChange:
61
                        dialog->lensSelected(this);
62
                        break;
63
                case ItemPositionHasChanged:
64
                        dialog->setLensPositionValues(mapToScene(rect().center()));
65
                        updateEffect();
66
                        break;
67
                default:
68
                        break;
69
        }
70
        return QGraphicsItem::itemChange(change, value);
71
}
72
 
73
void LensItem::updateEffect()
74
{
75
        LensItem *item;
76
        for (int a = 0; a < dialog->origPathItem.count(); a++)
77
        {
78
                QGraphicsPathItem* pItem = dialog->origPathItem[a];
79
                QPainterPath path = dialog->origPath[a];
10936 fschmid 80
                path = pItem->mapToScene(path);
10928 fschmid 81
                for (int b = 0; b < dialog->lensList.count(); b++)
82
                {
83
                        item = dialog->lensList[b];
84
                        path = lensDeform(path, item->mapToScene(item->rect().center()), item->rect().width() / 2.0, item->strength / 100.0);
85
                }
10936 fschmid 86
                path = pItem->mapFromScene(path);
10928 fschmid 87
                pItem->setPath(path);
88
        }
89
}
90
 
91
QPainterPath LensItem::lensDeform(const QPainterPath &source, const QPointF &offset, double m_radius, double s)
92
{
93
        QPainterPath path;
94
        path.addPath(source);
95
        for (int i = 0; i < path.elementCount(); ++i)
96
        {
97
                const QPainterPath::Element &e = path.elementAt(i);
98
                double dx = e.x - offset.x();
99
                double dy = e.y - offset.y();
100
                double len = m_radius - sqrt(dx * dx + dy * dy);
101
                if (len > 0)
102
                        path.setElementPositionAt(i, e.x - s * dx * len / m_radius, e.y - s * dy * len / m_radius);
103
        }
104
        return path;
105
}
106
 
107
LensDialog::LensDialog(QWidget* parent, ScribusDoc *doc) : QDialog(parent)
108
{
109
        setupUi(this);
110
        buttonRemove->setEnabled(false);
111
        setModal(true);
112
        buttonZoomOut->setIcon(QIcon(loadIcon("16/zoom-out.png")));
113
        buttonZoomI->setIcon(QIcon(loadIcon("16/zoom-in.png")));
114
 
115
        PageItem *currItem;
116
        double gx, gy, gh, gw;
117
        doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
118
        uint selectedItemCount = doc->m_Selection->count();
119
        if (selectedItemCount == 1)
120
        {
121
                currItem = doc->m_Selection->itemAt(0);
122
                gx = currItem->xPos();
123
                gy = currItem->yPos();
124
        }
10931 fschmid 125
        QStack<PageItem*> groupStack;
126
        QStack<QGraphicsPathItem*> groupStack2;
127
        QStack<PageItem*> groupStack3;
128
        groupStack2.push(0);
10928 fschmid 129
        for (uint i = 0; i < selectedItemCount; ++i)
130
        {
131
                currItem = doc->m_Selection->itemAt(i);
132
                FPointArray path = currItem->PoLine;
10931 fschmid 133
                QPainterPath pp;
134
                if (currItem->itemType() == PageItem::PolyLine)
135
                        pp = path.toQPainterPath(false);
136
                else
137
                        pp = path.toQPainterPath(true);
10928 fschmid 138
                origPath.append(pp);
10931 fschmid 139
                QGraphicsPathItem* pItem = new QGraphicsPathItem(pp, groupStack2.top());
140
                if (groupStack2.top() == 0)
141
                {
142
                        scene.addItem(pItem);
143
                        pItem->setPos(currItem->xPos() - gx, currItem->yPos() - gy);
10936 fschmid 144
                        pItem->rotate(currItem->rotation());
10931 fschmid 145
                }
146
                else
147
                {
148
                        PageItem* parent = groupStack3.top();
10936 fschmid 149
                        QMatrix mm;
150
                        mm.rotate(-parent->rotation());
151
                        mm.translate(-parent->xPos(), -parent->yPos());
152
                        pItem->setPos(mm.map(QPointF(currItem->xPos(), currItem->yPos())));
10931 fschmid 153
                }
154
                pItem->setZValue(i);
10928 fschmid 155
                origPathItem.append(pItem);
10936 fschmid 156
                if (((currItem->fillColor() == CommonStrings::None) && (currItem->GrType == 0)) || (currItem->controlsGroup()))
10928 fschmid 157
                        pItem->setBrush(Qt::NoBrush);
158
                else
10936 fschmid 159
                {
160
                        if (currItem->GrType != 0)
161
                        {
162
                                if (currItem->GrType != 8)
163
                                {
164
                                        QGradient pat;
165
                                        double x1 = currItem->GrStartX;
166
                                        double y1 = currItem->GrStartY;
167
                                        double x2 = currItem->GrEndX;
168
                                        double y2 = currItem->GrEndY;
169
                                        switch (currItem->GrType)
170
                                        {
171
                                                case 1:
172
                                                case 2:
173
                                                case 3:
174
                                                case 4:
175
                                                case 6:
176
                                                        pat = QLinearGradient(x1, y1,  x2, y2);
177
                                                        break;
178
                                                case 5:
179
                                                case 7:
180
                                                        pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), x1, y1);
181
                                                        break;
182
                                        }
183
                                        QList<VColorStop*> colorStops = currItem->fill_gradient.colorStops();
184
                                        QColor qStopColor;
185
                                        for( int offset = 0 ; offset < colorStops.count() ; offset++ )
186
                                        {
187
                                                qStopColor = colorStops[ offset ]->color;
188
                                                int h, s, v, sneu, vneu;
189
                                                int shad = colorStops[offset]->shade;
190
                                                qStopColor.getHsv(&h, &s, &v);
191
                                                sneu = s * shad / 100;
192
                                                vneu = 255 - ((255 - v) * shad / 100);
193
                                                qStopColor.setHsv(h, sneu, vneu);
194
                                                qStopColor.setAlphaF(colorStops[offset]->opacity);
195
                                                pat.setColorAt(colorStops[ offset ]->rampPoint, qStopColor);
196
                                        }
197
                                        pItem->setBrush(pat);
198
                                }
199
                                else if ((currItem->GrType == 8) && (!currItem->pattern().isEmpty()) && (doc->docPatterns.contains(currItem->pattern())))
200
                                {
201
                                        double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation;
202
                                        currItem->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation);
203
                                        QMatrix qmatrix;
204
                                        qmatrix.translate(patternOffsetX, patternOffsetY);
205
                                        qmatrix.rotate(patternRotation);
206
                                        qmatrix.scale(patternScaleX / 100.0, patternScaleY / 100.0);
207
                                        QImage pat = *doc->docPatterns[currItem->pattern()].getPattern();
208
                                        QBrush brush = QBrush(pat);
209
                                        brush.setMatrix(qmatrix);
210
                                        pItem->setBrush(brush);
211
                                }
212
                        }
213
                        else
214
                        {
215
                                QColor paint = ScColorEngine::getShadeColorProof(doc->PageColors[currItem->fillColor()], doc, currItem->fillShade());
216
                                paint.setAlphaF(1.0 - currItem->fillTransparency());
217
                                pItem->setBrush(paint);
218
                        }
219
                }
10928 fschmid 220
                if ((currItem->lineColor() == CommonStrings::None) || (currItem->controlsGroup()))
221
                        pItem->setPen(Qt::NoPen);
222
                else
10936 fschmid 223
                {
224
                        QColor paint = ScColorEngine::getShadeColorProof(doc->PageColors[currItem->lineColor()], doc, currItem->lineShade());
225
                        paint.setAlphaF(1.0 - currItem->lineTransparency());
226
                        pItem->setPen(QPen(paint, currItem->lineWidth(), currItem->lineStyle(), currItem->lineEnd(), currItem->lineJoin()));
227
                }
10931 fschmid 228
                if (currItem->controlsGroup())
229
                {
230
                        groupStack.push(currItem->groupsLastItem);
231
                        groupStack2.push(pItem);
232
                        groupStack3.push(currItem);
233
                        pItem->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
234
                }
235
                if (groupStack.count() != 0)
236
                {
237
                        while (currItem == groupStack.top())
238
                        {
239
                                groupStack3.pop();
240
                                groupStack2.pop();
241
                                groupStack.pop();
242
                                if (groupStack.count() == 0)
243
                                        break;
244
                        }
245
                }
10928 fschmid 246
        }
247
 
248
        previewWidget->setRenderHint(QPainter::Antialiasing);
249
        previewWidget->setScene(&scene);
10932 fschmid 250
        isFirst = true;
251
        addLens();
10928 fschmid 252
        connect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
253
        connect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
254
        connect(spinRadius, SIGNAL(valueChanged(double)), this, SLOT(setNewLensRadius(double)));
255
        connect(spinStrength, SIGNAL(valueChanged(double)), this, SLOT(setNewLensStrength(double)));
256
        connect(buttonAdd, SIGNAL(clicked()), this, SLOT(addLens()));
257
        connect(buttonRemove, SIGNAL(clicked()), this, SLOT(removeLens()));
258
        connect(buttonZoomI, SIGNAL(clicked()), this, SLOT(doZoomIn()));
259
        connect(buttonZoomOut, SIGNAL(clicked()), this, SLOT(doZoomOut()));
260
        connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
261
        connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
262
}
263
 
10932 fschmid 264
void LensDialog::showEvent(QShowEvent *e)
265
{
266
        QDialog::showEvent(e);
267
        if (isFirst)
268
                previewWidget->fitInView(scene.itemsBoundingRect(), Qt::KeepAspectRatio);
269
        isFirst = false;
270
}
271
 
10928 fschmid 272
void LensDialog::doZoomIn()
273
{
274
        previewWidget->scale(2.0, 2.0);
275
}
276
 
277
void LensDialog::doZoomOut()
278
{
279
        previewWidget->scale(0.5, 0.5);
280
}
281
 
282
void LensDialog::addLens()
283
{
284
        disconnect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
285
        disconnect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
286
        disconnect(spinRadius, SIGNAL(valueChanged(double)), this, SLOT(setNewLensRadius(double)));
287
        disconnect(spinStrength, SIGNAL(valueChanged(double)), this, SLOT(setNewLensStrength(double)));
288
        QRectF bBox = scene.itemsBoundingRect();
289
        double r = qMin(bBox.width(), bBox.height());
290
        double x = (bBox.width() - r) / 2.0;
291
        double y = (bBox.height() - r) / 2.0;
292
        LensItem *item = new LensItem(QRectF(x, y, r, r), this);
293
        scene.addItem(item);
294
        lensList.append(item);
295
        currentLens = lensList.count() - 1;
10931 fschmid 296
        item->setZValue(currentLens+999999);
10928 fschmid 297
        spinXPos->setValue(x + r / 2.0);
298
        spinYPos->setValue(y + r / 2.0);
299
        spinRadius->setValue(r / 2.0);
300
        spinStrength->setValue(100.0);
301
        lensList[currentLens]->updateEffect();
302
        if (lensList.count() > 1)
303
                buttonRemove->setEnabled(true);
304
        connect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
305
        connect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
306
        connect(spinRadius, SIGNAL(valueChanged(double)), this, SLOT(setNewLensRadius(double)));
307
        connect(spinStrength, SIGNAL(valueChanged(double)), this, SLOT(setNewLensStrength(double)));
308
}
309
 
310
void LensDialog::removeLens()
311
{
312
        LensItem *item = lensList.takeAt(currentLens);
313
        scene.removeItem(item);
314
        delete item;
315
        if (lensList.count() > 1)
316
                buttonRemove->setEnabled(true);
317
        else
318
                buttonRemove->setEnabled(false);
319
        currentLens = lensList.count() - 1;
320
        lensList[currentLens]->setSelected(true);
321
        lensList[currentLens]->updateEffect();
322
}
323
 
324
void LensDialog::lensSelected(LensItem *item)
325
{
326
        disconnect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
327
        disconnect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
328
        disconnect(spinRadius, SIGNAL(valueChanged(double)), this, SLOT(setNewLensRadius(double)));
329
        disconnect(spinStrength, SIGNAL(valueChanged(double)), this, SLOT(setNewLensStrength(double)));
330
        QPointF p = item->mapToScene(item->rect().center());
331
        spinXPos->setValue(p.x());
332
        spinYPos->setValue(p.y());
333
        spinRadius->setValue(item->rect().width() / 2.0);
334
        spinStrength->setValue(item->strength);
335
        currentLens = lensList.indexOf(item);
336
        if (currentLens < 0)
337
                currentLens = 0;
338
        connect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
339
        connect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
340
        connect(spinRadius, SIGNAL(valueChanged(double)), this, SLOT(setNewLensRadius(double)));
341
        connect(spinStrength, SIGNAL(valueChanged(double)), this, SLOT(setNewLensStrength(double)));
342
}
343
 
344
void LensDialog::setLensPositionValues(QPointF p)
345
{
346
        disconnect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
347
        disconnect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
348
        spinXPos->setValue(p.x());
349
        spinYPos->setValue(p.y());
350
        connect(spinXPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensX(double)));
351
        connect(spinYPos, SIGNAL(valueChanged(double)), this, SLOT(setNewLensY(double)));
352
}
353
 
354
void LensDialog::setNewLensX(double x)
355
{
356
        QRectF r = lensList[currentLens]->rect();
357
        r.moveCenter(QPointF(x, r.center().y()));
358
        lensList[currentLens]->setRect(r);
359
        lensList[currentLens]->updateEffect();
360
}
361
 
362
void LensDialog::setNewLensY(double y)
363
{
364
        QRectF r = lensList[currentLens]->rect();
365
        r.moveCenter(QPointF(r.center().x(), y));
366
        lensList[currentLens]->setRect(r);
367
        lensList[currentLens]->updateEffect();
368
}
369
 
370
void LensDialog::setNewLensRadius(double radius)
371
{
372
        QRectF r = lensList[currentLens]->rect();
373
        QPointF center = r.center();
374
        r.setWidth(radius * 2.0);
375
        r.setHeight(radius * 2.0);
376
        QPointF centerN = r.center();
377
        r.translate(center.x() - centerN.x(), center.y() - centerN.y());
378
        setLensPositionValues(lensList[currentLens]->mapToScene(r.center()));
379
        lensList[currentLens]->setRect(r);
380
        lensList[currentLens]->updateEffect();
381
}
382
 
383
void LensDialog::setNewLensStrength(double s)
384
{
385
        lensList[currentLens]->setStrength(s);
386
        lensList[currentLens]->updateEffect();
387
}