/***************************************************************************
 *   Copyright (C) 2004 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "strans.h"
#include "element.h"
 
strans::strans() {
    reset(); 
}

strans::~strans() {}

void strans::scale(const double d) {
    mag*=d;
	if (mag<0) {mag=-mag; angle+=180;}
    if (angle>=360) {
        angle-=360;
    }
    matrix.scale(d,d);
}

void strans::scale(const double x,const double y) {
    if (x==1&&y== -1) {
	toggleMirror_x();
	return;
	}
    mag*=(x+y)/2.0;
	if (mag<0) {mag=-mag; angle+=180;}
    if (angle>=360) {
        angle-=360;
    }
    matrix.scale(x,y);
}

void strans::reset() {
    mag=1;
    angle=0;
    mirror_x=false;
    matrix.setMatrix(1,0,0,1,0,0);
}

void strans::toggleMirror_x() {
    mirror_x=!mirror_x;
    matrix.scale(1,-1);
}

void strans::setMirror_x() {
    if (!mirror_x){
     toggleMirror_x();
    }
}
void strans::clearMirror_x() {
    if (mirror_x){
     toggleMirror_x();
    }
}

void strans::invert(){
 matrix=matrix.inverted();
 angle=-angle;
     if (angle>=360) {
        angle-=360;
    }
     if (angle<0) {
        angle+=360;
    }
 mag=1.0/mag;
}

void strans::rotate(const double a) {
    if (mirror_x) 
      {angle+=a;}
    else {angle-=a;}
    //angle-=a;
    if (angle>=360) {
        angle-=360;
    }
    if (angle<0) {
        angle+=360;
    }
    matrix.rotate(a);
}

void strans::translate(const int x,const int y){
    matrix.translate(x,y);
}

strans & strans::operator*= (const strans &t){
strans r;
mag=mag*t.mag;
if (mag<0) {mag=-mag; angle+=180;}
if (t.mirror_x^mirror_x) {angle+=t.angle;}
    else {angle-=t.angle;}
if (angle>=360) {
        angle-=360;
    }
if (angle<0) {
        angle+=360;
}
mirror_x=mirror_x ^ t.mirror_x;
matrix=matrix*t.matrix;
return *this;
}

QPoint strans::mapDraw (const QPoint p)const{
//return matrix.map(p);
if (angle!=0)  return QPoint(int(matrix.m11()*(qreal)(p.x()) + matrix.m21()*(qreal)(p.y()) + matrix.dx()),
                   int(matrix.m12()*(qreal)(p.x()) + matrix.m22()*(qreal)(p.y()) + matrix.dy()));
return QPoint(int(matrix.m11()*(qreal)(p.x()) + matrix.dx()),
                   int( matrix.m22()*(qreal)(p.y()) + matrix.dy()));

}

QPointF strans::mapDrawF (const QPoint p)const{
//return matrix.map(p);
return QPointF((matrix.m11()*(qreal)(p.x()) + matrix.m21()*(qreal)(p.y()) + matrix.dx()),
                   (matrix.m12()*(qreal)(p.x()) + matrix.m22()*(qreal)(p.y()) + matrix.dy()));
}

bool operator== (const strans &r1,const strans &r2){
if (r1.matrix!=r2.matrix) return false;
if (r1.angle!=r2.angle) return false;
if (r1.mag!=r2.mag) return false;
return true;
}

QPoint strans::mapIn(QPoint p)const{
  QMatrix m=QMatrix();
  m.reset();
  m.rotate(angle);
  m.scale(mag,mag);
  p=m.map(p);
  if (mirror_x){p.setY(-p.y());};
  return p;
}
QPoint strans::mapOut(QPoint p)const{
  QMatrix m=QMatrix();
  m.reset();
  if (mirror_x){p.setY(-p.y());};
  m.scale(1.0/mag,1.0/mag);
  m.rotate(-angle);
  p=m.map(p);
  return p;
}

