• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
NSBezierPath HiDPI
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

NSBezierPath HiDPI


  • Subject: NSBezierPath HiDPI
  • From: Steven Spencer <email@hidden>
  • Date: Sun, 11 Sep 2011 01:59:07 +0100

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 (email@hidden)

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:

This email sent to email@hidden

  • Prev by Date: OutlineView, drop between rows?
  • Next by Date: Re: OutlineView, drop between rows?
  • Previous by thread: Re: OutlineView, drop between rows?
  • Next by thread: Re: SecKeyRef object without KeyChain [issues with kSecPkcs1Padding]
  • Index(es):
    • Date
    • Thread