Re: Sit on it and rotate ??
Re: Sit on it and rotate ??
- Subject: Re: Sit on it and rotate ??
- From: Chris Meyer <email@hidden>
- Date: Wed, 11 Jul 2001 12:35:02 -0700
Hi Robert,
I noticed a bug in the code I sent you a few weeks ago to rotate an
image. I was assuming dstRect would always be equal to the bounds
rect; but that's not the case.
To fix it, add the line:
dstRect = [self bounds];
after the NSImage *image = [self image] line at the top of the function.
This implementation is somewhat inefficient in that it attempts to
draw the whole image every time it draws; but the underlying drawing
code seems to handle it quickly through clipping regions...
If I come up with a faster implementation, I'll forward the code to you.
Chris
- (void)drawRect:(NSRect)dstRect
{
NSImage *image = [self image];
dstRect = [self bounds];
if ( image != nil )
{
NSAffineTransform *transform = [NSAffineTransform transform];
NSRect fromRect, toRect;
NSSize size = [image size];
float scale,rotationDegrees;
fromRect.origin.x = 0;
fromRect.origin.y = 0;
fromRect.size = size;
if ( dstRect.size.width/size.width >
dstRect.size.height/size.height ) // scale so height fits
{
toRect.size.width = dstRect.size.height * (size.width/size.height);
toRect.size.height = dstRect.size.height;
toRect.origin.x = (dstRect.size.width - toRect.size.width)/2;
toRect.origin.y = 0;
}
else
// scale so width fits
{
toRect.size.width = dstRect.size.width;
toRect.size.height = dstRect.size.width * (size.height/size.width);
toRect.origin.x = 0;
toRect.origin.y = (dstRect.size.height - toRect.size.height)/2;
}
switch (m_rotation)
{
default:
case Zero:
{
scale = 1;
rotationDegrees = 0;
break;
}
case Ninety:
{
scale = toRect.size.width < toRect.size.height ?
dstRect.size.width/toRect.size.height :
dstRect.size.height/toRect.size.width;
rotationDegrees = -90;
break;
}
case OneEighty:
{
scale = 1;
rotationDegrees = -180;
break;
}
case TwoSeventy:
{
scale = toRect.size.width < toRect.size.height ?
dstRect.size.width/toRect.size.height :
dstRect.size.height/toRect.size.width;
rotationDegrees = 90;
break;
}
}
[transform translateXBy:dstRect.size.width/2
yBy:dstRect.size.height/2];
[transform rotateByDegrees:rotationDegrees];
[transform scaleBy:scale];
[transform translateXBy:-dstRect.size.width/2
yBy:-dstRect.size.height/2];
// erase the outside rects first so if we have pixel errors
we draw the image
// LAST!
{
NSRect toRect2;
[NSGraphicsContext saveGraphicsState];
[[NSColor blackColor] set];
toRect2.origin = [transform transformPoint:toRect.origin];
toRect2.size = [transform transformSize:toRect.size];
if ( toRect2.size.width < 0 )
{
toRect2.size.width = -toRect2.size.width;
toRect2.origin.x -= toRect2.size.width;
}
if ( toRect2.size.height < 0 )
{
toRect2.size.height = -toRect2.size.height;
toRect2.origin.y -= toRect2.size.height;
}
if ( NSMinX( dstRect ) < NSMinX( toRect2 ) )
NSRectFill( NSMakeRect( NSMinX( dstRect ), NSMinY( dstRect ),
NSMinX( toRect2 ) - NSMinX( dstRect ),
dstRect.size.height ) );
if ( NSMaxX( dstRect ) > NSMaxX( toRect2 ) )
NSRectFill( NSMakeRect( NSMaxX( toRect2 ), NSMinY( dstRect ),
NSMaxX( dstRect ) - NSMaxX( toRect2 ),
dstRect.size.height ) );
if ( NSMinY( dstRect ) < NSMinY( toRect2 ) )
NSRectFill( NSMakeRect( NSMinX( dstRect ), NSMinY( dstRect ),
dstRect.size.width, NSMinY( toRect2 ) - NSMinY(
dstRect ) ) );
if ( NSMaxY( dstRect ) > NSMaxY( toRect2 ) )
NSRectFill( NSMakeRect( NSMinX( dstRect ), NSMaxY( toRect2 ),
dstRect.size.width, NSMaxY( dstRect ) - NSMaxY(
toRect2 ) ) );
[NSGraphicsContext restoreGraphicsState];
}
[transform concat];
[image drawInRect:toRect fromRect:fromRect
operation:NSCompositeCopy fraction:1.0];
NSFrameRect( toRect );
[transform invert];
[transform concat];
}
else
{
NSEraseRect( dstRect );
}
}