Much optimised coordinate conversion

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@3783 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-02-22 09:00:53 +00:00
parent 7a8090d8a2
commit 369036d886
3 changed files with 104 additions and 205 deletions

View file

@ -1,3 +1,9 @@
Mon Feb 22 8:30:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* NSView.m: Tidied coordinate conversion code to use new system with
a cached conversion matrix to convert to/from window coordinates.
* NSView.h: Cache conversion matrices.
Mon Feb 22 6:06:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Mon Feb 22 6:06:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* NSView.m: Tidied coordinate conversion code to use new system with * NSView.m: Tidied coordinate conversion code to use new system with

View file

@ -76,7 +76,8 @@ enum {
NSRect bounds; NSRect bounds;
id frameMatrix; id frameMatrix;
id boundsMatrix; id boundsMatrix;
id windowMatrix; id matrixToWindow;
id matrixFromWindow;
NSView* super_view; NSView* super_view;
NSMutableArray *sub_views; NSMutableArray *sub_views;
@ -374,13 +375,8 @@ enum {
- (void) _invalidateCoordinates; - (void) _invalidateCoordinates;
- (void) _rebuildCoordinates; - (void) _rebuildCoordinates;
- (PSMatrix*)_frameMatrix; - (PSMatrix*)_matrixToWindow;
- (PSMatrix*)_boundsMatrix; - (PSMatrix*)_matrixFromWindow;
- (PSMatrix*)_windowMatrix;
- (PSMatrix*) _concatenateBoundsMatricesInReverseOrderFromPath: (NSArray*)p;
- (PSMatrix*) _concatenateMatricesInReverseOrderFromPath: (NSArray*)p;
- (NSMutableArray*) _pathBetweenSubview: (NSView*)subview
toSuperview: (NSView*)superview;
@end @end
#endif #endif

View file

@ -174,9 +174,10 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
bounds.origin = NSZeroPoint; // Set bounds rectangle bounds.origin = NSZeroPoint; // Set bounds rectangle
bounds.size = frame.size; bounds.size = frame.size;
frameMatrix = [PSMatrix new]; // init PS matrix for frameMatrix = [PSMatrix new]; // Map fromsuperview to frame
boundsMatrix = [PSMatrix new]; // frame and bounds boundsMatrix = [PSMatrix new]; // Map fromsuperview to bounds
windowMatrix = [PSMatrix new]; // map to window coordinates matrixToWindow = [PSMatrix new]; // Map to window coordinates
matrixFromWindow = [PSMatrix new]; // Map from window coordinates
[frameMatrix setFrameOrigin: frame.origin]; [frameMatrix setFrameOrigin: frame.origin];
sub_views = [NSMutableArray new]; sub_views = [NSMutableArray new];
@ -199,7 +200,8 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
- (void) dealloc - (void) dealloc
{ {
[windowMatrix release]; [matrixToWindow release];
[matrixFromWindow release];
[frameMatrix release]; [frameMatrix release];
[boundsMatrix release]; [boundsMatrix release];
[sub_views release]; [sub_views release];
@ -636,45 +638,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aPoint; return aPoint;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 matrix = [aView _matrixToWindow];
/*
* Convert from aView to window
*/
matrix = [aView _windowMatrix];
new = [matrix pointInMatrixSpace: aPoint]; new = [matrix pointInMatrixSpace: aPoint];
/*
* Convert from window to self.
*/
matrix = [[self _windowMatrix] copy];
[matrix inverse];
new = [matrix pointInMatrixSpace: new];
[matrix release];
#else
if ([self isDescendantOf: aView])
{
NSMutableArray *path;
path = [self _pathBetweenSubview: self toSuperview: aView]; if (coordinates_valid)
[path addObject: aView]; matrix = matrixFromWindow;
matrix = [self _concatenateMatricesInReverseOrderFromPath: path];
[matrix inverse];
new = [matrix pointInMatrixSpace: aPoint];
}
else if ([aView isDescendantOf: self])
{
NSMutableArray *path;
path = [self _pathBetweenSubview: aView toSuperview: self];
[path addObject: self];
matrix = [self _concatenateMatricesInReverseOrderFromPath: path];
new = [matrix pointInMatrixSpace: aPoint];
}
else else
{ matrix = [self _matrixFromWindow];
new = [aView convertPoint: aPoint toView: nil]; new = [matrix pointInMatrixSpace: new];
new = [self convertPoint: new fromView: nil];
}
#endif
return new; return new;
} }
@ -689,17 +661,16 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aPoint; return aPoint;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 if (coordinates_valid)
matrix = [self _windowMatrix]; matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
new = [matrix pointInMatrixSpace: aPoint]; new = [matrix pointInMatrixSpace: aPoint];
matrix = [[aView _windowMatrix] copy];
[matrix inverse]; matrix = [aView _matrixFromWindow];
new = [matrix pointInMatrixSpace: new]; new = [matrix pointInMatrixSpace: new];
[matrix release];
return new; return new;
#else
return [aView convertPoint: aPoint fromView: self];
#endif
} }
- (NSRect) convertRect: (NSRect)aRect fromView: (NSView*)aView - (NSRect) convertRect: (NSRect)aRect fromView: (NSView*)aView
@ -713,22 +684,20 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aRect; return aRect;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 matrix = [aView _matrixToWindow];
matrix = [aView _windowMatrix];
r.origin = [matrix pointInMatrixSpace: aRect.origin]; r.origin = [matrix pointInMatrixSpace: aRect.origin];
r.size = [matrix sizeInMatrixSpace: aRect.size]; r.size = [matrix sizeInMatrixSpace: aRect.size];
matrix = [[self _windowMatrix] copy];
[matrix inverse]; if (coordinates_valid)
matrix = matrixFromWindow;
else
matrix = [self _matrixFromWindow];
r.origin = [matrix pointInMatrixSpace: r.origin]; r.origin = [matrix pointInMatrixSpace: r.origin];
r.size = [matrix sizeInMatrixSpace: r.size]; r.size = [matrix sizeInMatrixSpace: r.size];
[matrix release];
#else
r = aRect;
r.origin = [self convertPoint: r.origin fromView: aView];
r.size = [self convertSize: r.size fromView: aView];
#endif
if ([aView isFlipped] != [self isFlipped]) if ([aView isFlipped] != [self isFlipped])
r.origin.y -= r.size.height; r.origin.y -= r.size.height;
return r; return r;
} }
@ -743,20 +712,17 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aRect; return aRect;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 if (coordinates_valid)
matrix = [self _windowMatrix]; matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
r.origin = [matrix pointInMatrixSpace: aRect.origin]; r.origin = [matrix pointInMatrixSpace: aRect.origin];
r.size = [matrix sizeInMatrixSpace: aRect.size]; r.size = [matrix sizeInMatrixSpace: aRect.size];
matrix = [[aView _windowMatrix] copy];
[matrix inverse]; matrix = [aView _matrixFromWindow];
r.origin = [matrix pointInMatrixSpace: r.origin]; r.origin = [matrix pointInMatrixSpace: r.origin];
r.size = [matrix sizeInMatrixSpace: r.size]; r.size = [matrix sizeInMatrixSpace: r.size];
[matrix release];
#else
r = aRect;
r.origin = [self convertPoint: r.origin toView: aView];
r.size = [self convertSize: r.size toView: aView];
#endif
if ([aView isFlipped] != [self isFlipped]) if ([aView isFlipped] != [self isFlipped])
r.origin.y -= r.size.height; r.origin.y -= r.size.height;
@ -774,41 +740,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aSize; return aSize;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 matrix = [aView _matrixToWindow];
/*
* Convert from aView to window
*/
matrix = [aView _windowMatrix];
new = [matrix sizeInMatrixSpace: aSize]; new = [matrix sizeInMatrixSpace: aSize];
/*
* Convert from window to self.
*/
matrix = [[self _windowMatrix] copy];
[matrix inverse];
new = [matrix sizeInMatrixSpace: new];
[matrix release];
#else
if ([self isDescendantOf: aView])
{
NSArray* path = [self _pathBetweenSubview: self toSuperview: aView];
matrix = [self _concatenateBoundsMatricesInReverseOrderFromPath: path]; if (coordinates_valid)
[matrix inverse]; matrix = matrixFromWindow;
new = [matrix sizeInMatrixSpace: aSize];
}
else if ([aView isDescendantOf: self])
{
NSArray* path = [self _pathBetweenSubview: aView toSuperview: self];
matrix = [self _concatenateBoundsMatricesInReverseOrderFromPath: path];
new = [matrix sizeInMatrixSpace: aSize];
}
else else
{ matrix = [self _matrixFromWindow];
new = [aView convertSize: aSize toView: nil]; new = [matrix sizeInMatrixSpace: new];
new = [self convertSize: new fromView: nil];
}
#endif
return new; return new;
} }
@ -823,17 +763,16 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aSize; return aSize;
NSAssert(window == [aView window], NSInvalidArgumentException); NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1 if (coordinates_valid)
matrix = [self _windowMatrix]; matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
new = [matrix sizeInMatrixSpace: aSize]; new = [matrix sizeInMatrixSpace: aSize];
matrix = [[aView _windowMatrix] copy];
[matrix inverse]; matrix = [aView _matrixFromWindow];
new = [matrix sizeInMatrixSpace: new]; new = [matrix sizeInMatrixSpace: new];
[matrix release];
return new; return new;
#else
return [aView convertSize: aSize fromView: self];
#endif
} }
- (void) setPostsFrameChangedNotifications: (BOOL)flag - (void) setPostsFrameChangedNotifications: (BOOL)flag
@ -1846,68 +1785,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
* Private methods. * Private methods.
*/ */
- (NSRect) _boundingRectFor: (NSRect)rect
{
NSRect new;
[frameMatrix boundingRectFor: rect result: &new];
return new;
}
- (PSMatrix*) _boundsMatrix
{
return boundsMatrix;
}
- (PSMatrix*) _concatenateBoundsMatricesInReverseOrderFromPath: (NSArray*)viewsPath
{
unsigned count = [viewsPath count];
PSMatrix* matrix = [[PSMatrix new] autorelease];
while (count > 0)
{
NSView* view = [viewsPath objectAtIndex: --count];
[matrix concatenateWith: view->boundsMatrix];
}
return matrix;
}
- (PSMatrix*) _concatenateMatricesInReverseOrderFromPath: (NSArray*)viewsPath
{
PSMatrix *matrix = [[PSMatrix new] autorelease];
unsigned i = [viewsPath count];
NSView *matrices[i];
NSView *parent;
BOOL wasFlipped;
BOOL isFlipped;
if (i-- < 2)
return matrix;
[viewsPath getObjects: matrices];
parent = matrices[i];
wasFlipped = [parent isFlipped];
while (i-- > 0)
{
NSView *view = matrices[i];
(*concatImp)(matrix, concatSel, view->frameMatrix);
isFlipped = [view isFlipped];
if (isFlipped != wasFlipped)
{
flip->matrix[5] = view->bounds.size.height;
(*concatImp)(matrix, concatSel, flip);
}
(*concatImp)(matrix, concatSel, view->boundsMatrix);
parent = view;
wasFlipped = isFlipped;
}
return matrix;
}
/*
* The [-_invalidateCoordinates] method marks the coordinate mapping
* matrices (matrixFromWindof and matrixToWindow) and the cached visible
* rectangle as invalid. It recursively invalidates the coordinates for
* all subviews as well.
* This method must be called whenever the size, shape or position of
* the view is changed in any way.
*/
- (void) _invalidateCoordinates - (void) _invalidateCoordinates
{ {
if (coordinates_valid == YES) if (coordinates_valid == YES)
@ -1933,26 +1819,39 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
} }
} }
- (PSMatrix*) _frameMatrix /*
* The [-_matrixFromWindow] method returns a matrix that can be used to
* map coordinates in the windows coordinate system to coordinates in the
* views coordinate system. It rebuilds the mapping matrices and
* visible rectangle cache if necessary.
* All coordinate transformations use this matrix.
*/
- (PSMatrix*) _matrixFromWindow
{ {
return frameMatrix; if (coordinates_valid == NO)
[self _rebuildCoordinates];
return matrixFromWindow;
} }
- (NSMutableArray*) _pathBetweenSubview: (NSView*)subview /*
toSuperview: (NSView*)_superview * The [-_matrixToWindow] method returns a matrix that can be used to
* map coordinates in the views coordinate system to coordinates in the
* windows coordinate system. It rebuilds the mapping matrices and
* visible rectangle cache if necessary.
* All coordinate transformations use this matrix.
*/
- (PSMatrix*) _matrixToWindow
{ {
NSMutableArray *array = [NSMutableArray array]; if (coordinates_valid == NO)
NSView *view = subview; [self _rebuildCoordinates];
return matrixToWindow;
while (view && view != _superview)
{
[array addObject: view];
view = view->super_view;
}
return array;
} }
/*
* The [-_rebuildCoordinates] method rebuilds the coordinate mapping
* matrices (matrixFromWindof and matrixToWindow) and the cached visible
* rectangle if they have been invalidated.
*/
- (void) _rebuildCoordinates - (void) _rebuildCoordinates
{ {
if (coordinates_valid == NO) if (coordinates_valid == NO)
@ -1961,29 +1860,34 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
if (!window) if (!window)
{ {
visibleRect = NSZeroRect; visibleRect = NSZeroRect;
[windowMatrix makeIdentityMatrix]; [matrixToWindow makeIdentityMatrix];
[matrixFromWindow makeIdentityMatrix];
} }
if (!super_view) if (!super_view)
{ {
visibleRect = bounds; visibleRect = bounds;
[windowMatrix makeIdentityMatrix]; [matrixToWindow makeIdentityMatrix];
[matrixFromWindow makeIdentityMatrix];
} }
else else
{ {
NSRect superviewsVisibleRect; NSRect superviewsVisibleRect;
BOOL wasFlipped = [super_view isFlipped]; BOOL wasFlipped = [super_view isFlipped];
float vals[6]; float vals[6];
PSMatrix *pMatrix = [super_view _windowMatrix]; PSMatrix *pMatrix = [super_view _matrixToWindow];
[pMatrix getMatrix: vals]; [pMatrix getMatrix: vals];
[windowMatrix setMatrix: vals]; [matrixToWindow setMatrix: vals];
(*concatImp)(windowMatrix, concatSel, frameMatrix); (*concatImp)(matrixToWindow, concatSel, frameMatrix);
if ([self isFlipped] != wasFlipped) if ([self isFlipped] != wasFlipped)
{ {
flip->matrix[5] = bounds.size.height; flip->matrix[5] = bounds.size.height;
(*concatImp)(windowMatrix, concatSel, flip); (*concatImp)(matrixToWindow, concatSel, flip);
} }
(*concatImp)(windowMatrix, concatSel, boundsMatrix); (*concatImp)(matrixToWindow, concatSel, boundsMatrix);
[matrixToWindow getMatrix: vals];
[matrixFromWindow setMatrix: vals];
[matrixFromWindow inverse];
superviewsVisibleRect = [self convertRect: [super_view visibleRect] superviewsVisibleRect = [self convertRect: [super_view visibleRect]
fromView: super_view]; fromView: super_view];
@ -1993,12 +1897,5 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
} }
} }
- (PSMatrix*) _windowMatrix
{
if (coordinates_valid == NO)
[self _rebuildCoordinates];
return windowMatrix;
}
@end @end