19#include <tqapplication.h>
26#include "kis_paint_device.h"
27#include "kis_rotate_visitor.h"
28#include "kis_progress_display_interface.h"
29#include "kis_iterators_pixel.h"
30#include "kis_selection.h"
31#include "kis_painter.h"
33void KisRotateVisitor::rotate(
double angle,
bool rotateAboutImageCentre, KisProgressDisplayInterface *progress)
35 KisPoint centreOfRotation;
37 if (rotateAboutImageCentre) {
38 centreOfRotation = KisPoint(m_dev->image()->width() / 2.0, m_dev->image()->height() / 2.0);
40 TQRect r = m_dev->exactBounds();
41 centreOfRotation = KisPoint(r.x() + (r.width() / 2.0), r.y() + (r.height() / 2.0));
44 m_progress = progress;
46 KisPaintDeviceSP rotated = rotate(m_dev, angle, centreOfRotation);
48 if (!m_dev->hasSelection()) {
53 m_dev->clearSelection();
57 TQRect r = rotated->extent();
60 p.bitBlt(r.x(), r.y(), COMPOSITE_OVER, rotated, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height());
64void KisRotateVisitor::shear(
double angleX,
double angleY, KisProgressDisplayInterface *progress)
66 const double pi=3.1415926535897932385;
67 double thetaX = angleX * pi / 180;
68 double shearX = tan(thetaX);
69 double thetaY = angleY * pi / 180;
70 double shearY = tan(thetaY);
72 TQRect r = m_dev->exactBounds();
74 const int xShearSteps = r.height();
75 const int yShearSteps = r.width();
77 m_progress = progress;
78 initProgress(xShearSteps + yShearSteps);
81 KisPaintDeviceSP sheared;
83 if (m_dev->hasSelection()) {
84 sheared =
new KisPaintDevice(m_dev->colorSpace(),
"sheared");
85 KisPainter p1(sheared);
86 p1.bltSelection(r.x(), r.y(), COMPOSITE_OVER, m_dev, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height());
88 sheared = xShear(sheared, shearX);
91 sheared = xShear(m_dev, shearX);
94 sheared = yShear(sheared, shearY);
96 if (!m_dev->hasSelection()) {
100 m_dev->clearSelection();
103 KisPainter p2(m_dev);
104 r = sheared->extent();
106 p2.bitBlt(r.x(), r.y(), COMPOSITE_OVER, sheared, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height());
112KisPaintDeviceSP KisRotateVisitor::rotateRight90(KisPaintDeviceSP src)
114 KisPaintDeviceSP dst =
new KisPaintDevice(src->colorSpace(),
"rotateright90");
115 dst->setX(src->getX());
116 dst->setY(src->getY());
118 TQ_INT32 pixelSize = src->pixelSize();
119 TQRect r = src->exactBounds();
122 for (TQ_INT32 y = r.bottom(); y >= r.top(); --y) {
123 KisHLineIteratorPixel hit = src->createHLineIterator(r.x(), y, r.width(),
false);
124 KisVLineIterator vit = dst->createVLineIterator(-y, r.x(), r.width(),
true);
126 while (!hit.isDone()) {
127 if (hit.isSelected()) {
128 memcpy(vit.rawData(), hit.rawData(), pixelSize);
140KisPaintDeviceSP KisRotateVisitor::rotateLeft90(KisPaintDeviceSP src)
142 KisPaintDeviceSP dst =
new KisPaintDevice(src->colorSpace(),
"rotateleft90");
144 TQ_INT32 pixelSize = src->pixelSize();
145 TQRect r = src->exactBounds();
148 for (TQ_INT32 y = r.top(); y <= r.bottom(); ++y) {
150 KisHLineIteratorPixel hit = src->createHLineIterator(r.x(), y, r.width(),
false);
151 KisVLineIterator vit = dst->createVLineIterator(y, -r.x() - r.width(), r.width(),
true);
153 hit += r.width() - 1;
154 while (!vit.isDone()) {
155 if (hit.isSelected()) {
156 memcpy(vit.rawData(), hit.rawData(), pixelSize);
168KisPaintDeviceSP KisRotateVisitor::rotate180(KisPaintDeviceSP src)
170 KisPaintDeviceSP dst =
new KisPaintDevice(src->colorSpace(),
"rotate180");
171 dst->setX(src->getX());
172 dst->setY(src->getY());
174 TQ_INT32 pixelSize = src->pixelSize();
175 TQRect r = src->exactBounds();
177 for (TQ_INT32 y = r.top(); y <= r.bottom(); ++y) {
178 KisHLineIteratorPixel srcIt = src->createHLineIterator(r.x(), y, r.width(),
false);
179 KisHLineIterator dstIt = dst->createHLineIterator( -r.x() - r.width(), -y, r.width(),
true);
181 srcIt += r.width() - 1;
182 while (!dstIt.isDone()) {
183 if (srcIt.isSelected()) {
184 memcpy(dstIt.rawData(), srcIt.rawData(), pixelSize);
195KisPaintDeviceSP KisRotateVisitor::rotate(KisPaintDeviceSP src,
double angle,
KisPoint centreOfRotation)
197 const double pi = 3.1415926535897932385;
199 if (angle >= 315 && angle < 360) {
201 }
else if (angle > -360 && angle < -45) {
205 TQRect r = src->exactBounds();
207 const int xShearSteps = r.height();
208 const int yShearSteps = r.width();
209 const int fixedRotateSteps = r.height();
211 KisPaintDeviceSP dst;
214 initProgress(fixedRotateSteps);
215 dst = rotateRight90(src);
216 }
else if (angle == 180) {
217 initProgress(fixedRotateSteps);
218 dst = rotate180(src);
219 }
else if (angle == 270) {
220 initProgress(fixedRotateSteps);
221 dst = rotateLeft90(src);
225 if (angle >= -45 && angle < 45) {
227 theta = angle * pi / 180;
229 initProgress(yShearSteps + (2 * xShearSteps));
231 else if (angle >= 45 && angle < 135) {
233 initProgress(fixedRotateSteps + yShearSteps + (2 * xShearSteps));
234 dst = rotateRight90(src);
235 theta = (angle - 90) * pi / 180;
237 else if (angle >= 135 && angle < 225) {
239 initProgress(fixedRotateSteps + yShearSteps + (2 * xShearSteps));
240 dst = rotate180(src);
241 theta = (angle - 180) * pi / 180;
245 initProgress(fixedRotateSteps + yShearSteps + (2 * xShearSteps));
246 dst = rotateLeft90(src);
247 theta = (angle - 270) * pi / 180;
250 double shearX = tan(theta / 2);
251 double shearY = sin(theta);
254 dst = xShear(dst, shearX);
256 dst = yShear(dst, shearY);
258 dst = xShear(dst, shearX);
261 double sinAngle = sin(angle * pi / 180);
262 double cosAngle = cos(angle * pi / 180);
264 KisPoint rotatedCentreOfRotation(
265 centreOfRotation.x() * cosAngle - centreOfRotation.y() * sinAngle,
266 centreOfRotation.x() * sinAngle + centreOfRotation.y() * cosAngle);
268 dst->setX((TQ_INT32)(dst->getX() + centreOfRotation.x() - rotatedCentreOfRotation.x()));
269 dst->setY((TQ_INT32)(dst->getY() + centreOfRotation.y() - rotatedCentreOfRotation.y()));
276KisPaintDeviceSP KisRotateVisitor::xShear(KisPaintDeviceSP src,
double shearX)
278 KisPaintDeviceSP dst =
new KisPaintDevice(src->colorSpace(),
"xShear");
279 dst->setX(src->getX());
280 dst->setY(src->getY());
282 TQRect r = src->exactBounds();
285 TQ_INT32 displacementInt;
288 for (TQ_INT32 y = r.top(); y <= r.bottom(); y++) {
291 displacement = -y * shearX;
293 displacementInt = (TQ_INT32)(floor(displacement));
294 weight = displacement - displacementInt;
296 TQ_UINT8 pixelWeights[2];
298 pixelWeights[0] =
static_cast<TQ_UINT8
>(weight * 255 + 0.5);
299 pixelWeights[1] = 255 - pixelWeights[0];
301 KisHLineIteratorPixel srcIt = src->createHLineIterator(r.x(), y, r.width() + 1,
false);
302 KisHLineIteratorPixel leftSrcIt = src->createHLineIterator(r.x() - 1, y, r.width() + 1,
false);
303 KisHLineIteratorPixel dstIt = dst->createHLineIterator(r.x() + displacementInt, y, r.width() + 1,
true);
305 while (!srcIt.isDone()) {
307 const TQ_UINT8 *pixelPtrs[2];
309 pixelPtrs[0] = leftSrcIt.rawData();
310 pixelPtrs[1] = srcIt.rawData();
312 src->colorSpace()->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData());
324KisPaintDeviceSP KisRotateVisitor::yShear(KisPaintDeviceSP src,
double shearY)
326 KisPaintDeviceSP dst =
new KisPaintDevice(src->colorSpace(),
"yShear");
327 dst->setX(src->getX());
328 dst->setY(src->getY());
330 TQRect r = src->exactBounds();
333 TQ_INT32 displacementInt;
336 for (TQ_INT32 x = r.left(); x <= r.right(); x++) {
339 displacement = x * shearY;
341 displacementInt = (TQ_INT32)(floor(displacement));
342 weight = displacement - displacementInt;
344 TQ_UINT8 pixelWeights[2];
346 pixelWeights[0] =
static_cast<TQ_UINT8
>(weight * 255 + 0.5);
347 pixelWeights[1] = 255 - pixelWeights[0];
349 KisVLineIteratorPixel srcIt = src->createVLineIterator(x, r.y(), r.height() + 1,
false);
350 KisVLineIteratorPixel leftSrcIt = src->createVLineIterator(x, r.y() - 1, r.height() + 1,
false);
351 KisVLineIteratorPixel dstIt = dst->createVLineIterator(x, r.y() + displacementInt, r.height() + 1,
true);
353 while (!srcIt.isDone()) {
355 const TQ_UINT8 *pixelPtrs[2];
357 pixelPtrs[0] = leftSrcIt.rawData();
358 pixelPtrs[1] = srcIt.rawData();
360 src->colorSpace()->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData());
372void KisRotateVisitor::initProgress(TQ_INT32 totalSteps)
374 if (!m_progress)
return;
376 m_progressTotalSteps = totalSteps;
378 m_lastProgressPerCent = 0;
381 m_progress->setSubject(
this,
true,
false);
382 emit notifyProgress(0);
386void KisRotateVisitor::incrementProgress()
388 if (!m_progress)
return;
391 TQ_INT32 progressPerCent = (m_progressStep * 100) / m_progressTotalSteps;
393 if (progressPerCent != m_lastProgressPerCent) {
394 m_lastProgressPerCent = progressPerCent;
395 emit notifyProgress(progressPerCent);
399void KisRotateVisitor::setProgressDone()
401 if (!m_progress)
return;
403 emit notifyProgressDone();
A double-based point class that can return it's coordinates approximated to integers.