~smartboyhw/ubuntu/raring/calligra/2.6.0-0ubuntu1

« back to all changes in this revision

Viewing changes to .pc/kubuntu_04_arm_compile.diff/krita/ui/canvas/kis_coordinates_converter.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2012-10-09 10:27:34 UTC
  • Revision ID: package-import@ubuntu.com-20121009102734-q7jgb678a27aoo96
Tags: 1:2.5.3-0ubuntu2
Add kubuntu_04_arm_compile.diff fix compilation on ARM

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2010 Dmitry Kazakov <dimula73@gmail.com>
 
3
 *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program 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
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
18
 */
 
19
 
 
20
#include <cmath>
 
21
 
 
22
#include "kis_coordinates_converter.h"
 
23
 
 
24
#include <QTransform>
 
25
#include <KoViewConverter.h>
 
26
 
 
27
#include <kis_config.h>
 
28
#include <kis_image.h>
 
29
 
 
30
 
 
31
struct KisCoordinatesConverter::Private {
 
32
    Private():
 
33
        isXAxisMirrored(false), isYAxisMirrored(false), rotationAngle(0.0) { }
 
34
    
 
35
    KisImageWSP image;
 
36
    
 
37
    bool isXAxisMirrored;
 
38
    bool isYAxisMirrored;
 
39
    qreal rotationAngle;
 
40
    QSizeF canvasWidgetSize;
 
41
    QPointF documentOffset;
 
42
    
 
43
    QTransform flakeToWidget;
 
44
    QTransform imageToDocument;
 
45
    QTransform documentToFlake;
 
46
    QTransform widgetToViewport;
 
47
};
 
48
 
 
49
/**
 
50
 * When vastScrolling value is less than 0.5 it is possible
 
51
 * that the whole scrolling area (viewport) will be smaller than
 
52
 * the size of the widget. In such cases the image should be
 
53
 * centered in the widget. Previously we used a special parameter
 
54
 * documentOrigin for this purpose, now the value for this
 
55
 * centering is calculated dynamically, helping the offset to
 
56
 * center the image inside the widget
 
57
 *
 
58
 * Note that the correction is null when the size of the document
 
59
 * plus vast scrolling reserve is larger than the widget. This
 
60
 * is always true for vastScrolling parameter > 0.5.
 
61
 */
 
62
 
 
63
QPointF KisCoordinatesConverter::centeringCorrection() const
 
64
{
 
65
    KisConfig cfg;
 
66
 
 
67
    QSize documentSize = imageRectInWidgetPixels().toAlignedRect().size();
 
68
    QPointF dPoint(documentSize.width(), documentSize.height());
 
69
    QPointF wPoint(m_d->canvasWidgetSize.width(), m_d->canvasWidgetSize.height());
 
70
 
 
71
    QPointF minOffset = -cfg.vastScrolling() * wPoint;
 
72
    QPointF maxOffset = dPoint - wPoint + cfg.vastScrolling() * wPoint;
 
73
 
 
74
    QPointF range = maxOffset - minOffset;
 
75
 
 
76
    range.rx() = qMin(range.x(), 0.0);
 
77
    range.ry() = qMin(range.y(), 0.0);
 
78
 
 
79
    range /= 2;
 
80
 
 
81
    return -range;
 
82
}
 
83
 
 
84
/**
 
85
 * The document offset and the position of the top left corner of the
 
86
 * image must always coincide, that is why we need to correct them to
 
87
 * and fro.
 
88
 *
 
89
 * When we change zoom level, the calculation of the new offset is
 
90
 * done by KoCanvasControllerWidget, that is why we just passively fix
 
91
 * the flakeToWidget transform to conform the offset and wait until
 
92
 * the canvas controller will recenter us.
 
93
 *
 
94
 * But when we do our own transformations of the canvas, like rotation
 
95
 * and mirroring, we cannot rely on the centering of the canvas
 
96
 * controller and we do it ourselves. Then we just set new offset and
 
97
 * return its value to be set in the canvas controller explicitly.
 
98
 */
 
99
 
 
100
void KisCoordinatesConverter::correctOffsetToTransformation()
 
101
{
 
102
    m_d->documentOffset = -(imageRectInWidgetPixels().topLeft() -
 
103
          centeringCorrection()).toPoint();
 
104
}
 
105
 
 
106
void KisCoordinatesConverter::correctTransformationToOffset()
 
107
{
 
108
    QPointF topLeft = imageRectInWidgetPixels().topLeft();
 
109
    QPointF diff = (-topLeft) - m_d->documentOffset;
 
110
    diff += centeringCorrection();
 
111
    m_d->flakeToWidget *= QTransform::fromTranslate(diff.x(), diff.y());
 
112
}
 
113
 
 
114
void KisCoordinatesConverter::recalculateTransformations()
 
115
{
 
116
    if(!m_d->image) return;
 
117
 
 
118
    m_d->imageToDocument = QTransform::fromScale(1 / m_d->image->xRes(),
 
119
                                                 1 / m_d->image->yRes());
 
120
 
 
121
    qreal zoomX, zoomY;
 
122
    KoZoomHandler::zoom(&zoomX, &zoomY);
 
123
    m_d->documentToFlake = QTransform::fromScale(zoomX, zoomY);
 
124
 
 
125
    correctTransformationToOffset();
 
126
 
 
127
    QRectF irect = imageRectInWidgetPixels();
 
128
    QRectF wrect = QRectF(QPoint(0,0), m_d->canvasWidgetSize);
 
129
    QRectF rrect = irect & wrect;
 
130
 
 
131
    QTransform reversedTransform = flakeToWidgetTransform().inverted();
 
132
    QRectF     canvasBounds      = reversedTransform.mapRect(rrect);
 
133
    QPointF    offset            = canvasBounds.topLeft();
 
134
 
 
135
    m_d->widgetToViewport = reversedTransform * QTransform::fromTranslate(-offset.x(), -offset.y());
 
136
}
 
137
 
 
138
 
 
139
KisCoordinatesConverter::KisCoordinatesConverter()
 
140
    : m_d(new Private) { }
 
141
 
 
142
KisCoordinatesConverter::~KisCoordinatesConverter()
 
143
{
 
144
    delete m_d;
 
145
}
 
146
 
 
147
void KisCoordinatesConverter::setCanvasWidgetSize(QSize size)
 
148
{
 
149
    m_d->canvasWidgetSize = size;
 
150
    recalculateTransformations();
 
151
}
 
152
 
 
153
void KisCoordinatesConverter::setImage(KisImageWSP image)
 
154
{
 
155
    m_d->image = image;
 
156
    recalculateTransformations();
 
157
}
 
158
 
 
159
void KisCoordinatesConverter::setDocumentOffset(const QPoint& offset)
 
160
{
 
161
    QPointF diff = m_d->documentOffset - offset;
 
162
    
 
163
    m_d->documentOffset = offset;
 
164
    m_d->flakeToWidget *= QTransform::fromTranslate(diff.x(), diff.y());
 
165
    recalculateTransformations();
 
166
}
 
167
 
 
168
QPoint KisCoordinatesConverter::documentOffset() const
 
169
{
 
170
    return QPoint(int(m_d->documentOffset.x()), int(m_d->documentOffset.y()));
 
171
}
 
172
 
 
173
qreal KisCoordinatesConverter::rotationAngle() const
 
174
{
 
175
    return m_d->rotationAngle;
 
176
}
 
177
 
 
178
void KisCoordinatesConverter::setZoom(qreal zoom)
 
179
{
 
180
    KoZoomHandler::setZoom(zoom);
 
181
    recalculateTransformations();
 
182
}
 
183
 
 
184
QPoint KisCoordinatesConverter::rotate(QPointF center, qreal angle)
 
185
{
 
186
    QTransform rot;
 
187
    rot.rotate(angle);
 
188
 
 
189
    m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(),-center.y());
 
190
    m_d->flakeToWidget *= rot;
 
191
    m_d->flakeToWidget *= QTransform::fromTranslate(center.x(), center.y());
 
192
    m_d->rotationAngle = std::fmod(m_d->rotationAngle + angle, 360.0);
 
193
 
 
194
    correctOffsetToTransformation();
 
195
    recalculateTransformations();
 
196
 
 
197
    return m_d->documentOffset.toPoint();
 
198
}
 
199
 
 
200
QPoint KisCoordinatesConverter::mirror(QPointF center, bool mirrorXAxis, bool mirrorYAxis, bool keepOrientation)
 
201
{
 
202
    bool       doXMirroring = m_d->isXAxisMirrored ^ mirrorXAxis;
 
203
    bool       doYMirroring = m_d->isYAxisMirrored ^ mirrorYAxis;
 
204
    qreal      scaleX       = doYMirroring ? -1.0 : 1.0;
 
205
    qreal      scaleY       = doXMirroring ? -1.0 : 1.0;
 
206
    QTransform mirror       = QTransform::fromScale(scaleX, scaleY);
 
207
    
 
208
    QTransform rot;
 
209
    rot.rotate(m_d->rotationAngle);
 
210
    
 
211
    m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(),-center.y());
 
212
    
 
213
    if(keepOrientation)
 
214
        m_d->flakeToWidget *= rot.inverted();
 
215
    
 
216
    m_d->flakeToWidget *= mirror;
 
217
    
 
218
    if(keepOrientation)
 
219
        m_d->flakeToWidget *= rot;
 
220
    
 
221
    m_d->flakeToWidget *= QTransform::fromTranslate(center.x(),center.y());
 
222
    
 
223
    if(!keepOrientation && (doXMirroring ^ doYMirroring))
 
224
        m_d->rotationAngle = -m_d->rotationAngle;
 
225
    
 
226
    m_d->isXAxisMirrored = mirrorXAxis;
 
227
    m_d->isYAxisMirrored = mirrorYAxis;
 
228
 
 
229
    correctOffsetToTransformation();
 
230
    recalculateTransformations();
 
231
 
 
232
    return m_d->documentOffset.toPoint();
 
233
}
 
234
 
 
235
QPoint KisCoordinatesConverter::resetRotation(QPointF center)
 
236
{
 
237
    QTransform rot;
 
238
    rot.rotate(-m_d->rotationAngle);
 
239
    
 
240
    m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(), -center.y());
 
241
    m_d->flakeToWidget *= rot;
 
242
    m_d->flakeToWidget *= QTransform::fromTranslate(center.x(), center.y());
 
243
    m_d->rotationAngle = 0.0;
 
244
 
 
245
    correctOffsetToTransformation();
 
246
    recalculateTransformations();
 
247
 
 
248
    return m_d->documentOffset.toPoint();
 
249
}
 
250
 
 
251
QTransform KisCoordinatesConverter::imageToWidgetTransform() const{
 
252
    return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToWidget;
 
253
}
 
254
 
 
255
QTransform KisCoordinatesConverter::imageToDocumentTransform() const {
 
256
    return m_d->imageToDocument;
 
257
}
 
258
 
 
259
QTransform KisCoordinatesConverter::flakeToWidgetTransform() const {
 
260
    return m_d->flakeToWidget;
 
261
}
 
262
 
 
263
QTransform KisCoordinatesConverter::documentToWidgetTransform() const
 
264
{
 
265
    return m_d->documentToFlake * m_d->flakeToWidget;
 
266
}
 
267
 
 
268
QTransform KisCoordinatesConverter::viewportToWidgetTransform() const {
 
269
    return m_d->widgetToViewport.inverted();
 
270
}
 
271
 
 
272
QTransform KisCoordinatesConverter::imageToViewportTransform() const {
 
273
    return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToWidget * m_d->widgetToViewport;
 
274
}
 
275
 
 
276
void KisCoordinatesConverter::getQPainterCheckersInfo(QTransform *transform,
 
277
                                                      QPointF *brushOrigin,
 
278
                                                      QPolygonF *polygon) const
 
279
{
 
280
    /**
 
281
     * Qt has different rounding for QPainter::drawRect/drawImage.
 
282
     * The image is rounded mathematically, while rect in aligned
 
283
     * to the next integer. That causes transparent line appear on
 
284
     * the canvas.
 
285
     *
 
286
     * See: https://bugreports.qt.nokia.com/browse/QTBUG-22827
 
287
     */
 
288
 
 
289
    QRectF imageRect = imageRectInViewportPixels();
 
290
    imageRect.adjust(0,0,-0.5,-0.5);
 
291
 
 
292
    KisConfig cfg;
 
293
    if (cfg.scrollCheckers()) {
 
294
        *transform = viewportToWidgetTransform();
 
295
        *polygon = imageRect;
 
296
        *brushOrigin = imageToViewport(QPointF(0,0));
 
297
    }
 
298
    else {
 
299
        *transform = QTransform();
 
300
        *polygon = viewportToWidgetTransform().map(imageRect);
 
301
        *brushOrigin = QPoint(0,0);
 
302
    }
 
303
}
 
304
 
 
305
void KisCoordinatesConverter::getOpenGLCheckersInfo(QTransform *textureTransform,
 
306
                                                    QTransform *modelTransform,
 
307
                                                    QRectF *textureRect,
 
308
                                                    QRectF *modelRect) const
 
309
{
 
310
    KisConfig cfg;
 
311
    QRectF viewportRect = imageRectInViewportPixels();
 
312
 
 
313
    if(cfg.scrollCheckers()) {
 
314
        *textureTransform = QTransform();
 
315
        *textureRect = QRectF(0, 0, viewportRect.width(),viewportRect.height());
 
316
    }
 
317
    else {
 
318
        *textureTransform = viewportToWidgetTransform();
 
319
        *textureRect = viewportRect;
 
320
    }
 
321
 
 
322
    *modelTransform = viewportToWidgetTransform();
 
323
    *modelRect = viewportRect;
 
324
}
 
325
 
 
326
QPointF KisCoordinatesConverter::imageCenterInWidgetPixel() const
 
327
{
 
328
    if(!m_d->image)
 
329
        return QPointF();
 
330
    
 
331
    QPolygonF poly = imageToWidget(QPolygon(m_d->image->bounds()));
 
332
    return (poly[0] + poly[1] + poly[2] + poly[3]) / 4.0;
 
333
}
 
334
 
 
335
 
 
336
// these functions return a bounding rect if the canvas is rotated
 
337
 
 
338
QRectF KisCoordinatesConverter::imageRectInWidgetPixels() const
 
339
{
 
340
    if(!m_d->image) return QRectF();
 
341
    return imageToWidget(m_d->image->bounds());
 
342
}
 
343
 
 
344
QRectF KisCoordinatesConverter::imageRectInViewportPixels() const
 
345
{
 
346
    if(!m_d->image) return QRectF();
 
347
    return imageToViewport(m_d->image->bounds());
 
348
}
 
349
 
 
350
QSizeF KisCoordinatesConverter::imageSizeInFlakePixels() const
 
351
{
 
352
    if(!m_d->image) return QSizeF();
 
353
 
 
354
    qreal scaleX, scaleY;
 
355
    imageScale(&scaleX, &scaleY);
 
356
    QSize imageSize = m_d->image->size();
 
357
 
 
358
    return QSizeF(imageSize.width() * scaleX, imageSize.height() * scaleY);
 
359
}
 
360
 
 
361
QRectF KisCoordinatesConverter::widgetRectInFlakePixels() const
 
362
{
 
363
    return widgetToFlake(QRectF(QPoint(0,0), m_d->canvasWidgetSize));
 
364
}
 
365
 
 
366
QPointF KisCoordinatesConverter::flakeCenterPoint() const
 
367
{
 
368
    QRectF widgetRect = widgetRectInFlakePixels();
 
369
    return QPointF(widgetRect.left() + widgetRect.width() / 2,
 
370
                   widgetRect.top() + widgetRect.height() / 2);
 
371
}
 
372
 
 
373
QPointF KisCoordinatesConverter::widgetCenterPoint() const
 
374
{
 
375
    return QPointF(m_d->canvasWidgetSize.width() / 2.0, m_d->canvasWidgetSize.height() / 2.0);
 
376
}
 
377
 
 
378
void KisCoordinatesConverter::imageScale(qreal *scaleX, qreal *scaleY) const
 
379
{
 
380
    // get the x and y zoom level of the canvas
 
381
    qreal zoomX, zoomY;
 
382
    KoZoomHandler::zoom(&zoomX, &zoomY);
 
383
 
 
384
    // Get the KisImage resolution
 
385
    qreal resX = m_d->image->xRes();
 
386
    qreal resY = m_d->image->yRes();
 
387
 
 
388
    // Compute the scale factors
 
389
    *scaleX = zoomX / resX;
 
390
    *scaleY = zoomY / resY;
 
391
}