{"id":11,"date":"2007-02-08T09:04:51","date_gmt":"2007-02-08T17:04:51","guid":{"rendered":"http:\/\/www.latenightsw.com\/blog\/?p=20"},"modified":"2007-02-08T09:04:51","modified_gmt":"2007-02-08T17:04:51","slug":"faster-ilifecontrols","status":"publish","type":"post","link":"http:\/\/markalldritt.com\/?p=11","title":{"rendered":"Faster iLifeControls"},"content":{"rendered":"<p>I&#8217;m working on a project that uses Sean Patrick O&#8217;Brien&#8217;s <a href=\"http:\/\/www.seanpatrickobrien.com\/2006\/09\/28\/ilifecontrols-10\/\">iLifeControls<\/a>.  My application is a QuickTime editing tool, and I quickly ran into performance problems that I traced to the NFIFrame class within iLifeControls.  Here is an updated version of NFIFrame that consumes ~50% less CPU time doing a window refresh.<\/p>\n\n<p><strong>NOTE<\/strong>: My changes are enclosed in #ifdef FASTER blocks.<\/p>\n\n<p>NFIFrame.h<\/p>\n\n<pre>\n\/\/\n\/\/  NFIFrame.h\n\/\/  iLife Window\n\/\/\n\/\/  Created by Sean Patrick O'Brien on 9\/15\/06.\n\/\/  Copyright 2006 Sean Patrick O'Brien. All rights reserved.\n\/\/\n\n#import <cocoa\/Cocoa.h>\n\n#import \"NSGrayFrame.h\"\n\n#define FASTER 1\n\n@class NSGrayFrame;\n\n@interface NFIFrame : NSGrayFrame {\n    float mTitleBarHeight;\n    float mBottomBarHeight;\n    float mMidBarHeight;\n    float mMidBarOriginY;\n\n    id mInnerGradient;\n    id mOuterGradient;\n\n#if FASTER\n    NSImage* mCachedBackground;\n#endif\n}\n\n+ (NSBezierPath*)_clippingPathForFrame:(NSRect)frame;\n+ (float)cornerRadius;\n\n- (void)_drawTitleBar:(NSRect)rect;\n- (void)_drawMidBar:(NSRect)rect;\n- (void)_drawBottomBar:(NSRect)rect;\n- (void)_drawTitle:(NSRect)rect;\n\n- (id)backgroundColor;\n- (id)gradientStartColor;\n- (id)gradientEndColor;\n- (id)gradient2StartColor;\n- (id)gradient2EndColor;\n- (id)edgeColor;\n- (id)bottomEdgeColor;\n- (id)topWindowEdgeColor;\n- (id)bottomWindowEdgeColor;\n- (id)titleColor;\n\n- (float)titleBarHeight;\n- (void)setTitleBarHeight:(float)height;\n- (float)bottomBarHeight;\n- (void)setBottomBarHeight:(float)height;\n- (float)midBarHeight;\n- (float)midBarOriginY;\n- (void)setMidBarHeight:(float)height origin:(float)origin;\n\n@end\n<\/pre>\n\n<p>NFIFrame.m<\/p>\n\n<pre>\n\/\/\n\/\/  NFIFrame.m\n\/\/  CustomWindow\n\/\/\n\/\/  Created by Sean Patrick O'Brien on 9\/15\/06.\n\/\/  Copyright 2006 Sean Patrick O'Brien. All rights reserved.\n\/\/\n\n#import \"NFIFrame.h\"\n\n#import \"CTGradient.h\"\n#import \"EtchedTextCell.h\"\n#import \"NSImage+FrameworkImage.h\"\n\n@implementation NFIFrame\n\n- (id)initWithFrame:(struct _NSRect)frame styleMask:(unsigned int)style owner:(id)o\n{\n    self = [super initWithFrame:frame styleMask:style owner:o];\n    mTitleBarHeight = 25.0f;\n    mBottomBarHeight = 0;\n    mMidBarOriginY = 0;\n    mMidBarHeight = 0;\n\n    mInnerGradient = [[CTGradient gradientWithBeginningColor: [self gradientStartColor]\n                        endingColor:[self gradientEndColor]] retain];\n    mOuterGradient = [[CTGradient gradientWithBeginningColor: [self gradient2StartColor]\n                        endingColor:[self gradient2EndColor]] retain];\n\n    titleCell = [[EtchedTextCell alloc] initTextCell: @\"\"];\n    [titleCell setFont:[NSFont fontWithName:@\"LucidaGrande\" size:13.0]];\n    [titleCell setShadowColor:[NSColor whiteColor]];\n\n    return self;\n}\n\n#if FASTER\n- (void) dealloc\n{\n    [mCachedBackground release];\n    [super dealloc];\n}\n#endif\n\n- (NSSize)_topCornerSize\n{\n    return NSMakeSize(0, [self titleBarHeight]);\n}\n\n+ (NSBezierPath*)_clippingPathForFrame:(NSRect)aRect\n{\n    float radius = [self cornerRadius];\n    NSBezierPath *path = [NSBezierPath alloc];\n    NSPoint topMid = NSMakePoint(NSMidX(aRect), NSMaxY(aRect));\n    NSPoint topLeft = NSMakePoint(NSMinX(aRect), NSMaxY(aRect));\n    NSPoint topRight = NSMakePoint(NSMaxX(aRect), NSMaxY(aRect));\n    NSPoint bottomRight = NSMakePoint(NSMaxX(aRect), NSMinY(aRect));\n\n    [path moveToPoint: topMid];\n    [path appendBezierPathWithArcFromPoint: topRight\n        toPoint: bottomRight\n        radius: radius];\n    [path appendBezierPathWithArcFromPoint: bottomRight\n        toPoint: aRect.origin\n        radius: radius];\n    [path appendBezierPathWithArcFromPoint: aRect.origin\n        toPoint: topLeft\n        radius: radius];\n    [path appendBezierPathWithArcFromPoint: topLeft\n        toPoint: topRight\n        radius: radius];\n    [path closePath];\n\n    return path;\n}\n\n- (void)_drawTitle:(NSRect)rect\n{\n    [self _drawTitleStringIn:rect withColor:[self titleColor]];\n}\n\n- (void)_drawTitleBar:(NSRect)rect\n{\n    [[self topWindowEdgeColor] set];\n    NSRectFill(rect);\n    rect.size.height--;\n    [[self bottomEdgeColor] set];\n    NSRectFill(rect);\n    rect.size.height++;\n\n    NSRect gradientRect = rect;\n    gradientRect.origin.y++;\n    gradientRect.size.height -= 2;\n    [mOuterGradient fillRect: gradientRect angle:-90.0f];\n    gradientRect.origin.x++;\n    gradientRect.size.width -= 2;\n    [mInnerGradient fillRect: gradientRect angle:-90.0f];\n\n    NSImage *topLeft = [NSImage frameworkImageNamed: @\"IWWindowCornerTL\"];\n    NSImage *topRight = [NSImage frameworkImageNamed: @\"IWWindowCornerTR\"];\n\n    [topLeft compositeToPoint:NSMakePoint(rect.origin.x,\n                rect.origin.y + [self titleBarHeight] - [topLeft size].height) operation: NSCompositeSourceOver];\n    [topRight compositeToPoint:NSMakePoint(rect.origin.x + rect.size.width-[topRight size].width,\n                rect.origin.y + [self titleBarHeight] - [topLeft size].height) operation: NSCompositeSourceOver];\n\n    [self _drawTitle:rect];\n}\n\n- (void)_drawMidBar:(NSRect)rect\n{\n    [[self bottomWindowEdgeColor] set];\n    NSRectFill(rect);\n    rect.origin.y++;\n    rect.size.height--;\n    [[self bottomEdgeColor] set];\n    NSRectFill(rect);\n    rect.size.height -= 2;\n    rect.origin.y++;\n    [[self edgeColor] set];\n    NSRectFill(rect);\n    rect.size.height += 3;\n    rect.origin.y -= 2;\n\n    NSRect gradientRect = rect;\n    gradientRect.origin.y++;\n    gradientRect.size.height -= 3;\n    [mOuterGradient fillRect: gradientRect angle:-90.0f];\n    gradientRect.origin.x++;\n    gradientRect.size.width -= 2;\n    [mInnerGradient fillRect: gradientRect angle:-90.0f];\n}\n\n- (void)_drawBottomBar:(NSRect)rect\n{\n    [[self bottomWindowEdgeColor] set];\n    NSRectFill(rect);\n    rect.origin.y++;\n    rect.size.height--;\n    [[self bottomEdgeColor] set];\n    NSRectFill(rect);\n    rect.size.height -= 2;\n    rect.origin.y++;\n    [[self edgeColor] set];\n    NSRectFill(rect);\n    rect.size.height += 3;\n    rect.origin.y -= 2;\n\n    NSRect gradientRect = rect;\n    gradientRect.origin.y++;\n    gradientRect.size.height -= 3;\n    [mOuterGradient fillRect: gradientRect angle:-90.0f];\n    gradientRect.origin.x++;\n    gradientRect.size.width -= 2;\n    [mInnerGradient fillRect: gradientRect angle:-90.0f];\n\n    NSImage *bottomLeft = [NSImage frameworkImageNamed: @\"IWWindowCornerBL\"];\n    NSImage *bottomRight = [NSImage frameworkImageNamed: @\"IWWindowCornerBR\"];\n\n    [bottomLeft compositeToPoint:NSMakePoint(rect.origin.x, rect.origin.y) operation: NSCompositeSourceOver];\n    [bottomRight compositeToPoint:NSMakePoint(rect.origin.x + rect.size.width-[bottomRight size].width, rect.origin.y) operation: NSCompositeSourceOver];\n}\n\n- (void)drawRect:(struct _NSRect)_rect\n{\n    NSRect rect = [self bounds];\n#if FASTER\n    NSSize size = mCachedBackground ? [mCachedBackground size] : NSZeroSize;\n\n    if (!mCachedBackground || size.width != NSWidth(rect) || size.height != NSHeight(rect))\n    {\n        [mCachedBackground release];\n\n        mCachedBackground = [[NSImage alloc] initWithSize:rect.size];\n        [mCachedBackground lockFocus];\n        {\n            [[NSColor clearColor] set];\n            NSRectFill(_rect);\n\n            NSBezierPath *path = [[self class] _clippingPathForFrame: rect];\n            [path addClip];\n\n            [[self backgroundColor] set];\n\n            NSRectFill(rect);\n\n            NSRect titleBarRect = rect;\n            titleBarRect.origin.y += rect.size.height - [self titleBarHeight];\n            titleBarRect.size.height = [self titleBarHeight];\n\n            NSRect bottomBarRect = rect;\n            bottomBarRect.size.height = [self bottomBarHeight];\n\n            NSRect midBarRect = rect;\n            midBarRect.origin.y += [self midBarOriginY];\n            midBarRect.size.height = [self midBarHeight];\n\n            [self _drawMidBar: midBarRect];\n            [self _drawTitleBar: titleBarRect];\n            [self _drawBottomBar: bottomBarRect];\n        }\n        [mCachedBackground unlockFocus];\n    }\n\n    [[NSColor clearColor] set];\n    NSRectFill(NSUnionRect(rect, _rect));\n    [mCachedBackground drawInRect:_rect\n                         fromRect:_rect\n                        operation:NSCompositeSourceOver\n                         fraction:1.0];\n#else\n    [[NSColor clearColor] set];\n\n    NSRectFill(rect);\n    NSRectFill(_rect);\n\n    NSBezierPath *path = [[self class] _clippingPathForFrame: rect];\n    [path addClip];\n\n    [[self backgroundColor] set];\n\n    NSRectFill(rect);\n\n    NSRect titleBarRect = rect;\n    titleBarRect.origin.y += rect.size.height - [self titleBarHeight];\n    titleBarRect.size.height = [self titleBarHeight];\n\n    NSRect bottomBarRect = rect;\n    bottomBarRect.size.height = [self bottomBarHeight];\n\n    NSRect midBarRect = rect;\n    midBarRect.origin.y += [self midBarOriginY];\n    midBarRect.size.height = [self midBarHeight];\n\n    [self _drawMidBar: midBarRect];\n    [self _drawTitleBar: titleBarRect];\n    [self _drawBottomBar: bottomBarRect];\n#endif\n}\n\n- (void)_drawGrowBoxWithClip:(struct _NSRect)rect\n{\n    rect.origin.x += 3;\n    rect.origin.y += 2;\n    NSImage *resize = [NSImage frameworkImageNamed:@\"IWWindowResizeControl\"];\n    [resize compositeToPoint:rect.origin operation: NSCompositeSourceOver];\n}\n\n- (float)titleBarHeight\n{\n    if([self _toolbarIsShown])\n        return mTitleBarHeight + [self _distanceFromToolbarBaseToTitlebar];\n    return mTitleBarHeight;\n}\n\n- (void)setTitleBarHeight:(float)height\n{\n    mTitleBarHeight = height;\n#if FASTER\n    [mCachedBackground release];\n    mCachedBackground = nil;\n#endif\n    [self setNeedsDisplay:YES];\n}\n\n- (float)bottomBarHeight\n{\n    return mBottomBarHeight;\n}\n\n- (void)setBottomBarHeight:(float)height\n{\n    mBottomBarHeight = height;\n#if FASTER\n    [mCachedBackground release];\n    mCachedBackground = nil;\n#endif\n    [self setNeedsDisplay:YES];\n}\n\n- (float)midBarHeight\n{\n    return mMidBarHeight;\n}\n\n- (float)midBarOriginY\n{\n    return mMidBarOriginY;\n}\n\n- (void)setMidBarHeight:(float)height origin:(float)origin\n{\n    mMidBarHeight = height;\n    mMidBarOriginY = origin;\n#if FASTER\n    [mCachedBackground release];\n    mCachedBackground = nil;\n#endif\n    [self setNeedsDisplay:YES];\n}\n\n- (NSRect)contentRectForFrameRect:(NSRect)frameRect styleMask:(unsigned int)aStyle\n{\n    frameRect.size.height -= 25;\/\/[self titleBarHeight];\n    return frameRect;\n}\n\n- (NSRect)frameRectForContentRect:(NSRect)windowContent styleMask:(unsigned int)aStyle\n{\n    windowContent.size.height += 25;\/\/[self titleBarHeight];\n    return windowContent;\n}\n\n- (void)_showToolbarWithAnimation:(BOOL)animate\n{\n    [super _showToolbarWithAnimation:animate];\n    [self setNeedsDisplay:YES];\n}\n\n- (id)backgroundColor\n{\n    return [NSColor colorWithCalibratedWhite: 224\/255.0 alpha: 1.0];\n}\n\n- (id)gradientStartColor\n{\n    return [NSColor colorWithCalibratedWhite: 197\/255.0 alpha: 1.0];\n}\n\n- (id)gradientEndColor\n{\n    return [NSColor colorWithCalibratedWhite: 150\/255.0 alpha: 1.0];\n}\n\n- (id)gradient2StartColor\n{\n    return [NSColor colorWithCalibratedWhite: 179\/255.0 alpha: 1.0];\n}\n\n- (id)gradient2EndColor\n{\n    return [NSColor colorWithCalibratedWhite: 139\/255.0 alpha: 1.0];\n}\n\n- (id)edgeColor\n{\n    return [NSColor colorWithCalibratedWhite: 226\/255.0 alpha: 1.0];\n}\n\n- (id)bottomEdgeColor\n{\n    return [NSColor colorWithCalibratedWhite: 102\/255.0 alpha: 1.0];\n}\n\n- (id)topWindowEdgeColor\n{\n    return [NSColor colorWithCalibratedWhite: 222\/255.0 alpha: 1.0];\n}\n\n- (id)bottomWindowEdgeColor\n{\n    return [NSColor colorWithCalibratedWhite: 65\/255.0 alpha: 1.0];\n}\n\n- (id)titleColor\n{\n    if([[self window] isMainWindow])\n        return [NSColor colorWithCalibratedWhite:0 alpha:0.9];\n    return [NSColor colorWithCalibratedWhite:0 alpha:0.50];\n}\n\n+ (float)cornerRadius\n{\n    return 5.0;\n}\n\n@end\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m working on a project that uses Sean Patrick O&#8217;Brien&#8217;s iLifeControls. My application is a QuickTime editing tool, and I quickly ran into performance problems&#8230;<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"http:\/\/markalldritt.com\/?p=11\">Continue Reading<span class=\"screen-reader-text\">Faster iLifeControls<\/span><\/a><\/div><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[8],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7AQk-b","_links":{"self":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts\/11"}],"collection":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11"}],"version-history":[{"count":0,"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts\/11\/revisions"}],"wp:attachment":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}