mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 19:21:16 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@3222 72102866-910b-0410-8b05-ffd578937521
292 lines
6.4 KiB
Objective-C
292 lines
6.4 KiB
Objective-C
/*
|
|
PSMatrix.m
|
|
|
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
|
|
|
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
|
Date: August 1997
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <gnustep/gui/config.h>
|
|
#include <math.h>
|
|
|
|
#include <Foundation/NSString.h>
|
|
|
|
#include <AppKit/config.h>
|
|
#include <AppKit/PSMatrix.h>
|
|
|
|
/* A Postscript matrix look like this:
|
|
|
|
/ a b 0 \
|
|
| c d 0 |
|
|
\ tx ty 1 /
|
|
|
|
*/
|
|
|
|
static const float pi = 3.1415926535897932384626433;
|
|
|
|
@implementation PSMatrix
|
|
|
|
+ matrixFrom: (const float[6])_matrix
|
|
{
|
|
PSMatrix* m = [[self alloc] autorelease];
|
|
|
|
memcpy (m->matrix, _matrix, sizeof (m->matrix));
|
|
|
|
return m;
|
|
}
|
|
|
|
- init
|
|
{
|
|
[self makeIdentityMatrix];
|
|
rotationAngle = 0;
|
|
return self;
|
|
}
|
|
|
|
- (id)copyWithZone:(NSZone*)zone
|
|
{
|
|
PSMatrix* new = [isa alloc];
|
|
|
|
memcpy (new->matrix, matrix, sizeof(matrix));
|
|
new->rotationAngle = rotationAngle;
|
|
return new;
|
|
}
|
|
|
|
- (void)scaleBy:(float)sx :(float)sy
|
|
{
|
|
A *= sx; B *= sx;
|
|
C *= sy; D *= sy;
|
|
}
|
|
|
|
- (void)scaleTo:(float)sx :(float)sy
|
|
{
|
|
float angle = rotationAngle;
|
|
|
|
A = sx; B = 0;
|
|
C = 0; D = sy;
|
|
if (rotationAngle) {
|
|
[self rotateByAngle:angle];
|
|
rotationAngle = angle;
|
|
}
|
|
}
|
|
- (void)translateToPoint:(NSPoint)point
|
|
{
|
|
float newTX, newTY;
|
|
|
|
newTX = point.x * A + point.y * C + TX;
|
|
newTY = point.x * B + point.y * D + TY;
|
|
TX = newTX;
|
|
TY = newTY;
|
|
}
|
|
|
|
- (void)rotateByAngle:(float)angle
|
|
{
|
|
float newA, newB, newC, newD;
|
|
float angleRad = pi * angle / 180;
|
|
float sine = sin (angleRad);
|
|
float cosine = cos (angleRad);
|
|
|
|
newA = A * cosine + C * sine; newB = B * cosine + D * sine;
|
|
newC = -A * sine + C * cosine; newD = -B * sine + D * cosine;
|
|
|
|
A = newA; B = newB;
|
|
C = newC; D = newD;
|
|
|
|
rotationAngle += angle;
|
|
}
|
|
|
|
- (void)makeIdentityMatrix
|
|
{
|
|
A = 1; B = 0;
|
|
C = 0; D = 1;
|
|
TX = 0; TY = 0;
|
|
rotationAngle = 0;
|
|
}
|
|
|
|
- (void)setFrameOrigin:(NSPoint)point
|
|
{
|
|
float dx = point.x - TX;
|
|
float dy = point.y - TY;
|
|
[self translateToPoint:NSMakePoint (dx, dy)];
|
|
}
|
|
|
|
- (void)setFrameRotation:(float)angle
|
|
{
|
|
float newAngle = angle - rotationAngle;
|
|
[self rotateByAngle:newAngle];
|
|
}
|
|
|
|
- (float)rotationAngle
|
|
{
|
|
return rotationAngle;
|
|
}
|
|
|
|
- (void)concatenateWith:(PSMatrix*)other
|
|
{
|
|
float newA, newB, newC, newD, newTX, newTY;
|
|
|
|
newA = other->A * A + other->B * C;
|
|
newB = other->A * B + other->B * D;
|
|
newC = other->C * A + other->D * C;
|
|
newD = other->C * B + other->D * D;
|
|
newTX = other->TX * A + other->TY * C + TX;
|
|
newTY = other->TX * B + other->TY * D + TY;
|
|
|
|
A = newA; B = newB;
|
|
C = newC; D = newD;
|
|
TX = newTX; TY = newTY;
|
|
|
|
rotationAngle += other->rotationAngle;
|
|
}
|
|
|
|
- (void)inverse
|
|
{
|
|
float newA, newB, newC, newD, newTX, newTY;
|
|
float det;
|
|
|
|
det = A * D - B * C;
|
|
if (!det) {
|
|
NSLog (@"error: determinant of matrix is 0!");
|
|
return;
|
|
}
|
|
|
|
newA = D / det;
|
|
newB = -B / det;
|
|
newC = -C / det;
|
|
newD = A / det;
|
|
newTX = (-D * TX + C * TY) / det;
|
|
newTY = (B * TX - A * TY) / det;
|
|
|
|
NSDebugLog (@"inverse of matrix ((%f, %f) (%f, %f) (%f, %f))\n"
|
|
@"is ((%f, %f) (%f, %f) (%f, %f))",
|
|
A, B, C, D, TX, TY,
|
|
newA, newB, newC, newD, newTX, newTY);
|
|
|
|
A = newA; B = newB;
|
|
C = newC; D = newD;
|
|
TX = newTX; TY = newTY;
|
|
}
|
|
|
|
- (BOOL)isRotated
|
|
{
|
|
return rotationAngle != 0;
|
|
}
|
|
|
|
- (void)boundingRectFor:(NSRect)rect result:(NSRect*)new
|
|
{
|
|
float angle = rotationAngle
|
|
- ((int)(rotationAngle / 360)) * rotationAngle;
|
|
float angleRad = pi * angle / 180;
|
|
float angle90Rad = pi * (angle + 90) / 180;
|
|
float cosWidth, cosHeight, sinWidth, sinHeight;
|
|
/* Shortcuts of the usual rect values */
|
|
float x = rect.origin.x;
|
|
float y = rect.origin.y;
|
|
float width = rect.size.width;
|
|
float height = rect.size.height;
|
|
|
|
if (rotationAngle == 0) {
|
|
*new = NSZeroRect;
|
|
return;
|
|
}
|
|
|
|
cosWidth = cos(angleRad);
|
|
cosHeight = cos(angle90Rad);
|
|
sinWidth = sin(angleRad);
|
|
sinHeight = sin(angle90Rad);
|
|
|
|
if (angle <= 90) {
|
|
new->origin.x = x + height * cosHeight;
|
|
new->origin.y = y;
|
|
new->size.width = width * cosWidth - height * cosHeight;
|
|
new->size.height = width * sinWidth + height * sinHeight;
|
|
}
|
|
else if (angle <= 180) {
|
|
new->origin.x = x + width * cosWidth + height * cosHeight;
|
|
new->origin.y = y + height * sinHeight;
|
|
new->size.width = -width * cosWidth - height * cosHeight;
|
|
new->size.height = width * sinWidth - height * sinHeight;
|
|
}
|
|
else if (angle <= 270) {
|
|
new->origin.x = x + width * cosWidth;
|
|
new->origin.y = y + width * sinWidth + height * sinHeight;
|
|
new->size.width = -width * cosWidth + height * cosHeight;
|
|
new->size.height = -width * sinWidth - height * sinHeight;
|
|
}
|
|
else {
|
|
new->origin.x = x;
|
|
new->origin.y = y;
|
|
new->size.width = width * cosWidth + height * cosHeight;
|
|
new->size.height = width * sinWidth + height * sinHeight;
|
|
}
|
|
}
|
|
|
|
- (NSPoint)pointInMatrixSpace:(NSPoint)point
|
|
{
|
|
NSPoint new;
|
|
|
|
new.x = A * point.x + C * point.y + TX;
|
|
new.y = B * point.x + D * point.y + TY;
|
|
|
|
return new;
|
|
}
|
|
|
|
- (NSSize)sizeInMatrixSpace:(NSSize)size
|
|
{
|
|
NSSize new;
|
|
|
|
new.width = A * size.width + C * size.height;
|
|
new.height = B * size.width + D * size.height;
|
|
|
|
return new;
|
|
}
|
|
|
|
- (NSRect)rectInMatrixSpace:(NSRect)rect
|
|
{
|
|
NSRect new;
|
|
|
|
new.origin.x = A * rect.origin.x + C * rect.origin.y + TX;
|
|
new.origin.y = B * rect.origin.x + D * rect.origin.y + TY;
|
|
new.size.width = A * rect.size.width + C * rect.size.height;
|
|
new.size.height = B * rect.size.width + D * rect.size.height;
|
|
|
|
return new;
|
|
}
|
|
|
|
- (NSString*)description
|
|
{
|
|
return [NSString stringWithFormat:@"PSMatrix ((%f, %f) (%f, %f) (%f, %f))",
|
|
A, B, C, D, TX, TY];
|
|
}
|
|
|
|
- (void) setMatrix: (const float[6])replace
|
|
{
|
|
memcpy (matrix, replace, sizeof (matrix));
|
|
rotationAngle = atan2(replace[2], replace[0]);
|
|
rotationAngle *= 180.0 / M_PI;
|
|
|
|
}
|
|
|
|
- (void) getMatrix: (float[6])replace
|
|
{
|
|
memcpy (replace, matrix, sizeof (matrix));
|
|
}
|
|
|
|
@end /* PSMatrix */
|
|
|