Hello,

What is the correct way to draw a pixel aligned bezier path for HiDPI display 
modes ?
I've got the following code to draw a rounded rectangle in both standard 
1440x900 and HiDPI 720x450 resolutions, 
though it seems overly complex.
Is there a simpler solution, perhaps an api method ?
I have to rerun the code for it to take account of a display resolution change, 
how do I fix this ?

Thanks.

Steven


Lion, Xcode 4.1, Garbage collection on.
--------------------------------------------------

#import <Cocoa/Cocoa.h>

@interface TestView : NSView
{
    NSBezierPath *thePath;
}
- (NSAffineTransform *)transformationToDrawBezierPath:(NSBezierPath *)path 
                                        alignedInView:(NSView *)view 
                                           centredAtX:(CGFloat)x
                                                    y:(CGFloat)y
                                       alignPathWidth:(BOOL)alignPathWidth;
@end

--------------------------------------------------

#import "TestView.h"

@implementation TestView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        NSRect bounds = NSMakeRect(100.0, 100.0, 60.0, 60.0);    
        thePath = [NSBezierPath bezierPathWithRoundedRect:bounds xRadius:6.0 
yRadius:6.0];
        [thePath setLineWidth:0.0];
    }
    
    return self;
}

- (BOOL)isFlipped
{
    return YES;
}

- (void)drawRect:(NSRect)dirtyRect
{
    NSAffineTransform* transform = [self transformationToDrawBezierPath:thePath
                                                          alignedInView:self
                                                             centredAtX:123.0
                                                                      y:84.0
                                                         alignPathWidth:YES];   
 
    [transform concat];
    [[NSColor blueColor] set];
    [thePath stroke];
    [transform invert];
    [transform concat];
}

- (NSAffineTransform *)transformationToDrawBezierPath:(NSBezierPath *)path 
                                        alignedInView:(NSView *)view 
                                           centredAtX:(CGFloat)x
                                                    y:(CGFloat)y
                                       alignPathWidth:(BOOL)alignPathWidth;
{
    CGFloat onePixelWidth = [self convertSizeFromBacking:NSMakeSize(1.0, 
1.0)].width;
    CGFloat halfPixelWidth = onePixelWidth * 0.5; 
    NSInteger lineWidthPixelCount = MAX(1, (NSInteger) round([path lineWidth] / 
onePixelWidth));
    BOOL isLineWidthEven = lineWidthPixelCount %2 == 0;

    NSRect pathBounds = [path bounds];
    NSRect alignedBounds = [self centerScanRect:pathBounds];
    NSRect insideBounds;
    NSPoint pathCentrePoint = NSMakePoint(NSMidX(pathBounds), 
NSMidY(pathBounds));

    //Note : used centerScanRect to align the target point as, 
convertPointToBacking, 
    //only modified the y coordinate (followed by convertPointFromBacking).
    NSRect target = [self centerScanRect:NSMakeRect(x, y, 1.0, 1.0)];
        
    if (isLineWidthEven) {
        //Place an even line width path between pixels
        insideBounds = alignedBounds;
    } else {
        //Inset an odd line width path on the centre of pixels
        insideBounds = NSInsetRect(alignedBounds, halfPixelWidth, 
halfPixelWidth);
    }

    if (alignPathWidth) {
        [path setLineWidth:lineWidthPixelCount * onePixelWidth];
    }
    
    CGFloat xScale = insideBounds.size.width  / pathBounds.size.width;
    CGFloat yScale = insideBounds.size.height / pathBounds.size.height;
    CGFloat xScaleInverse = 1.0 / xScale;
    CGFloat yScaleInverse = 1.0 / yScale;

    NSAffineTransform* transform = [NSAffineTransform transform];

    //Scale about the path centre
    [transform translateXBy:pathCentrePoint.x 
                        yBy:pathCentrePoint.y];

    [transform scaleXBy:xScale
                    yBy:yScale];

    //Position the path
    [transform translateXBy:-pathCentrePoint.x + ((target.origin.x - 
pathCentrePoint.x) * xScaleInverse)
                        yBy:-pathCentrePoint.y + ((target.origin.y - 
pathCentrePoint.y) * yScaleInverse)];

    return transform;
}

@end

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to