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 Frith-MacDonald 1999-02-22 09:00:53 +00:00
parent f99c78791f
commit a136e2ee9c
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>
* NSView.m: Tidied coordinate conversion code to use new system with

View file

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

View file

@ -174,9 +174,10 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
bounds.origin = NSZeroPoint; // Set bounds rectangle
bounds.size = frame.size;
frameMatrix = [PSMatrix new]; // init PS matrix for
boundsMatrix = [PSMatrix new]; // frame and bounds
windowMatrix = [PSMatrix new]; // map to window coordinates
frameMatrix = [PSMatrix new]; // Map fromsuperview to frame
boundsMatrix = [PSMatrix new]; // Map fromsuperview to bounds
matrixToWindow = [PSMatrix new]; // Map to window coordinates
matrixFromWindow = [PSMatrix new]; // Map from window coordinates
[frameMatrix setFrameOrigin: frame.origin];
sub_views = [NSMutableArray new];
@ -199,7 +200,8 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
- (void) dealloc
{
[windowMatrix release];
[matrixToWindow release];
[matrixFromWindow release];
[frameMatrix release];
[boundsMatrix release];
[sub_views release];
@ -636,45 +638,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aPoint;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
/*
* Convert from aView to window
*/
matrix = [aView _windowMatrix];
matrix = [aView _matrixToWindow];
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];
[path addObject: aView];
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];
}
if (coordinates_valid)
matrix = matrixFromWindow;
else
{
new = [aView convertPoint: aPoint toView: nil];
new = [self convertPoint: new fromView: nil];
}
#endif
matrix = [self _matrixFromWindow];
new = [matrix pointInMatrixSpace: new];
return new;
}
@ -689,17 +661,16 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aPoint;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
matrix = [self _windowMatrix];
if (coordinates_valid)
matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
new = [matrix pointInMatrixSpace: aPoint];
matrix = [[aView _windowMatrix] copy];
[matrix inverse];
matrix = [aView _matrixFromWindow];
new = [matrix pointInMatrixSpace: new];
[matrix release];
return new;
#else
return [aView convertPoint: aPoint fromView: self];
#endif
}
- (NSRect) convertRect: (NSRect)aRect fromView: (NSView*)aView
@ -713,22 +684,20 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aRect;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
matrix = [aView _windowMatrix];
matrix = [aView _matrixToWindow];
r.origin = [matrix pointInMatrixSpace: aRect.origin];
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.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])
r.origin.y -= r.size.height;
return r;
}
@ -743,20 +712,17 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aRect;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
matrix = [self _windowMatrix];
if (coordinates_valid)
matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
r.origin = [matrix pointInMatrixSpace: aRect.origin];
r.size = [matrix sizeInMatrixSpace: aRect.size];
matrix = [[aView _windowMatrix] copy];
[matrix inverse];
matrix = [aView _matrixFromWindow];
r.origin = [matrix pointInMatrixSpace: r.origin];
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])
r.origin.y -= r.size.height;
@ -774,41 +740,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aSize;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
/*
* Convert from aView to window
*/
matrix = [aView _windowMatrix];
matrix = [aView _matrixToWindow];
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];
[matrix inverse];
new = [matrix sizeInMatrixSpace: aSize];
}
else if ([aView isDescendantOf: self])
{
NSArray* path = [self _pathBetweenSubview: aView toSuperview: self];
matrix = [self _concatenateBoundsMatricesInReverseOrderFromPath: path];
new = [matrix sizeInMatrixSpace: aSize];
}
if (coordinates_valid)
matrix = matrixFromWindow;
else
{
new = [aView convertSize: aSize toView: nil];
new = [self convertSize: new fromView: nil];
}
#endif
matrix = [self _matrixFromWindow];
new = [matrix sizeInMatrixSpace: new];
return new;
}
@ -823,17 +763,16 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
return aSize;
NSAssert(window == [aView window], NSInvalidArgumentException);
#if 1
matrix = [self _windowMatrix];
if (coordinates_valid)
matrix = matrixToWindow;
else
matrix = [self _matrixToWindow];
new = [matrix sizeInMatrixSpace: aSize];
matrix = [[aView _windowMatrix] copy];
[matrix inverse];
matrix = [aView _matrixFromWindow];
new = [matrix sizeInMatrixSpace: new];
[matrix release];
return new;
#else
return [aView convertSize: aSize fromView: self];
#endif
}
- (void) setPostsFrameChangedNotifications: (BOOL)flag
@ -1846,68 +1785,15 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
* 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
{
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];
NSView *view = subview;
while (view && view != _superview)
{
[array addObject: view];
view = view->super_view;
}
return array;
if (coordinates_valid == NO)
[self _rebuildCoordinates];
return matrixToWindow;
}
/*
* The [-_rebuildCoordinates] method rebuilds the coordinate mapping
* matrices (matrixFromWindof and matrixToWindow) and the cached visible
* rectangle if they have been invalidated.
*/
- (void) _rebuildCoordinates
{
if (coordinates_valid == NO)
@ -1961,29 +1860,34 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
if (!window)
{
visibleRect = NSZeroRect;
[windowMatrix makeIdentityMatrix];
[matrixToWindow makeIdentityMatrix];
[matrixFromWindow makeIdentityMatrix];
}
if (!super_view)
{
visibleRect = bounds;
[windowMatrix makeIdentityMatrix];
[matrixToWindow makeIdentityMatrix];
[matrixFromWindow makeIdentityMatrix];
}
else
{
NSRect superviewsVisibleRect;
BOOL wasFlipped = [super_view isFlipped];
float vals[6];
PSMatrix *pMatrix = [super_view _windowMatrix];
PSMatrix *pMatrix = [super_view _matrixToWindow];
[pMatrix getMatrix: vals];
[windowMatrix setMatrix: vals];
(*concatImp)(windowMatrix, concatSel, frameMatrix);
[matrixToWindow setMatrix: vals];
(*concatImp)(matrixToWindow, concatSel, frameMatrix);
if ([self isFlipped] != wasFlipped)
{
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]
fromView: super_view];
@ -1993,12 +1897,5 @@ static SEL invalidateSel = @selector(_invalidateCoordinates);
}
}
- (PSMatrix*) _windowMatrix
{
if (coordinates_valid == NO)
[self _rebuildCoordinates];
return windowMatrix;
}
@end