<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.3" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Vacuous Virtuoso &#187; CoreGraphics</title>
	<link>http://lipidity.com</link>
	<description>Despotic Development</description>
	<pubDate>Wed, 02 Apr 2008 14:18:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
	<language>en</language>
			<item>
		<title>More CoreGraphics Hackery</title>
		<link>http://lipidity.com/apple/cocoa/cgsinternal/</link>
		<comments>http://lipidity.com/apple/cocoa/cgsinternal/#comments</comments>
		<pubDate>Sat, 12 Jan 2008 04:21:03 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Apple]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Review]]></category>

		<guid isPermaLink="false">http://lipidity.com/apple/cocoa/cgsinternal/</guid>
		<description><![CDATA[Alacatia Labs, Inc. bring you the most thorough investigation of undocumented CoreGraphics functions to date, with CGSInternal.

There&#8217;s a subversion repository as well if you&#8217;re keen to stay up to date.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://alacatialabs.com/">Alacatia Labs, Inc.</a> bring you the most thorough investigation of undocumented <a href="http://lipidity.com/tag/core-graphics+animation">CoreGraphics</a> functions to date, with <a href="http://alacatialabs.com/toys/cgsinternal/">CGSInternal</a>.</p>

<p>There&#8217;s a <a href="http://svn.alacatialabs.com/CGSInternal/trunk/">subversion repository</a> as well if you&#8217;re keen to stay up to date.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/cocoa/cgsinternal/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CTGradient code bloat</title>
		<link>http://lipidity.com/apple/ctgradient-code-bloat/</link>
		<comments>http://lipidity.com/apple/ctgradient-code-bloat/#comments</comments>
		<pubDate>Tue, 20 Nov 2007 21:05:12 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Review]]></category>

		<category><![CDATA[Source Code]]></category>

		<category><![CDATA[Tutorial]]></category>

		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://lipidity.com/apple/cgradient-code-bloat/</guid>
		<description><![CDATA[While getting rid of extraneous junk in an application package is easy using Trimmit, the only way to prevent &#34;code bloat&#34; (and accompanying excess RAM and CPU usage) is through good programming practices. Where most developers fall short is in poor optimization of borrowed code. Let&#8217;s take CTGradient as an example as it&#8217;s well known [...]]]></description>
			<content:encoded><![CDATA[<p>While getting rid of extraneous junk in an application package is easy using <a href="http://lipidity.com/software/trimmit/">Trimmit</a>, the only way to prevent &quot;code bloat&quot; (and accompanying excess RAM and CPU usage) is through good programming practices. Where most developers fall short is in poor optimization of borrowed code. Let&#8217;s take CTGradient as an example as it&#8217;s well known and used (or more accurately, abused) in dozens of applications.</p>

<!--more-->

<p>CTGradient contains an incredible diversity of built-in gradients, gradient styles, and methods for creating fancy rainbows, radial gradients, linear gradients, aqua gradients, and a number of other interesting class and instance methods. It allows you to dynamically alter gradients by adding or removing colors, changing the level of transparency, filling NSRects or NSBezierPaths, rotating the gradient, etc. For demonstration purposes, all these features are excellent. For production, this is a nightmare.</p>

<p><strong><a href="http://pub.lipidity.com/CTGradient/CTGradient.m">CTGradient.m</a> weighs in at over 1300 lines of code.</strong></p>

<p>Ignoring Mr. Weider&#8217;s unique style of formatting, take a look through the code. If you&#8217;re putting this class in an application, you can immediately remove over a thousand lines. Just like that. But if you take some time to understand what&#8217;s going on, you can optimize this thing till it runs like a Ferrari.</p>

<p>You&#8217;ll notice <a href="http://lipidity.com/software/trimmit/">Trimmit</a> uses a gradient background for it&#8217;s window. Let&#8217;s cut down CTGradient until it matches the level of optimization of Trimmit&#8217;s gradient code.</p>

<h2>Clear the junk</h2>

<p>Firstly, let&#8217;s remove the methods we know for sure we won&#8217;t need. Remove the following methods completely from both the interface and the implementation (scroll down for more):</p>

<pre style='height:340px;overflow:scroll'><code>// We don't need the preset gradients

+ (id)dividerGradient;
+ (id)statusBarGradient;
+ (id)aquaSelectedGradient;
+ (id)aquaNormalGradient;
+ (id)aquaPressedGradient;
+ (id)unifiedSelectedGradient;
+ (id)unifiedNormalGradient;
+ (id)unifiedPressedGradient;
+ (id)unifiedDarkGradient;
+ (id)sourceListSelectedGradient;
+ (id)sourceListUnselectedGradient;
+ (id)rainbowGradient;
+ (id)hydrogenSpectrumGradient;

// We won't make any drastic modifications to the gradient once created

- (CTGradient *)gradientWithAlphaComponent:(float)alpha;
- (CTGradient *)addColorStop:(NSColor *)color atPosition:(float)position;
- (CTGradient *)removeColorStopAtIndex:(unsigned)index;
- (CTGradient *)removeColorStopAtPosition:(float)position;
- (CTGradientBlendingMode)blendingMode;
- (NSColor *)colorStopAtIndex:(unsigned)index;
- (NSColor *)colorAtPosition:(float)position;

// Now we don't need to conform to the NSCopying and NSCoding protocols

- (id)copyWithZone:(NSZone *)zone;
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)initWithCoder:(NSCoder *)coder;

// We only need to fill a simple NSRect

- (void)drawSwatchInRect:(NSRect)rect;
- (void)radialFillRect:(NSRect)rect;
- (void)fillBezierPath:(NSBezierPath *)path angle:(float)angle;
- (void)radialFillBezierPath:(NSBezierPath *)path;

// Remove the entire (Private) category;
// but leave -addElement:

- (void)_commonInit;
// move setBlendingMode code into init
- (void)setBlendingMode:(CTGradientBlendingMode)mode;
- (CTGradientElement *)elementAtIndex:(unsigned)index;
- (CTGradientElement)removeElementAtIndex:(unsigned)index;
- (CTGradientElement)removeElementAtPosition:(float)position;
</code></pre>

<p>The following C functions are now unused:</p>

<pre><code>static void chromaticEvaluation(void *info, const float *in, float *out);
static void inverseChromaticEvaluation(void *info, const float *in, float *out);
static void transformRGB_HSV(float *components);
static void transformHSV_RGB(float *components);
static void resolveHSV(float *color1, float *color2);
</code></pre>

<p>And also remove the following from the header:</p>

<pre><code>typedef enum  _CTBlendingMode
    {
    CTLinearBlendingMode,
    CTChromaticBlendingMode,
    CTInverseChromaticBlendingMode
    } CTGradientBlendingMode;
</code></pre>

<p>Remove the <code>&lt;protocols&gt;</code> and unnecessary instance variables so the interface looks like this:</p>

<pre><code>@interface CTGradient : NSObject {
    CTGradientElement* elementList;
    CGFunctionRef gradientFunction;
}
+ (id)gradientWithBeginningColor:(NSColor *)begin endingColor:(NSColor *)end;
- (void)fillRect:(NSRect)rect angle:(float)angle;
- (void)addElement:(CTGradientElement *)newElement;
@end
</code></pre>

<p>Before we go further, we&#8217;ll need to take a detour and fix the remaining code so that it compiles. That&#8217;s easy enough - just remove any references to code we&#8217;ve removed.</p>

<p>If you&#8217;ve been following along, your CTGradient should now look like <a href="http://pub.lipidity.com/CTGradient/CTGradient2.m">this</a> (also made it readable!).</p>

<p>In a few short minutes, we&#8217;re down from more than <strong>1300</strong> to a little over <strong>200 lines</strong>.</p>

<p><big>It gets better.</big></p>

<h2>Optimize it</h2>

<p>First stop, <code>fillRect:angle:</code>. Since the gradient for Trimmit&#8217;s window only runs vertically (angle 90), we can straight away take out the <var>angle</var> argument, and also cut the entire if / else structure with the angle down to the two lines that are under the <code>if(angle == 90)</code>. Ah, much better.</p>

<p>Now things start getting a teeny bit more complex - and fun.</p>

<hr />

<p>The CTGradient code is written so that one can have many different color stops. The CTGradientElement struct has a nextElement which points to the next CTGradientElement and the position of the current element is stored under the float <var>position</var>. However, we need just two - the starting and ending shades.</p>

<p>Let&#8217;s take a look at cutting the multiple elements down to just two.</p>

<p>The <code>addElement:</code> method has a lot of looping to insert the element at the correct place. However, since we know that we only ever need two, we can cut it down to this:</p>

<pre><code>- (void)addElement:(CTGradientElement *)newElement {
    if(elementList) {
        // elementList exists, add second element
        elementList-&gt;nextElement = malloc(sizeof(CTGradientElement));
        *(elementList-&gt;nextElement) = *newElement;
        elementList-&gt;nextElement-&gt;nextElement = 0;
    } else {
        // no elements - add first element
        elementList = malloc(sizeof(CTGradientElement));
        *elementList = *newElement;
        elementList-&gt;nextElement = 0;
    }
}
</code></pre>

<p>Similarly with <code>dealloc</code>,</p>

<pre><code>- (void)dealloc {
    CGFunctionRelease(gradientFunction);
    free(elementList-&gt;nextElement);
    free(elementList);
    [super dealloc];
}
</code></pre>

<p>While we&#8217;re at it, let&#8217;s clean up <code>init</code> as well:</p>

<pre><code>- (id)init {
    if(self = [super init]) {
        CGFunctionCallbacks evaluationCallbackInfo = {0 , &amp;linearEvaluation, 0};
        static const float input_value_range[2] = { 0, 1 };
        static const float output_value_ranges[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
        gradientFunction = CGFunctionCreate(&amp;elementList, 1, input_value_range, 4, output_value_ranges, &amp;evaluationCallbackInfo);
    }
    return self;
}
</code></pre>

<p>Now we head to the <code>linearEvaluation</code> function. <var>info</var> passed in refers to <var>elementList</var> (see the CGFunctionCreate call). Again, since we know that we&#8217;ll only ever have two elements we can reduce it to:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    float position = *in;

    CTGradientElement *color1 = *(CTGradientElement **)info;
    CTGradientElement *color2 = color1-&gt;nextElement;

    out[0] = (color2-&gt;red - color1-&gt;red)*position + color1-&gt;red; 
    out[1] = (color2-&gt;green - color1-&gt;green)*position + color1-&gt;green;
    out[2] = (color2-&gt;blue - color1-&gt;blue)*position + color1-&gt;blue;
    out[3] = (color2-&gt;alpha - color1-&gt;alpha)*position + color1-&gt;alpha;
}
</code></pre>

<p>And now we can finally remove the lines from <code>+gradientWithBeginningColor:endingColor:</code> where the positions are set, and also remove the <var>position</var> float from the CTGradientElement struct.</p>

<hr />

<p>We&#8217;re now down to a little over <strong>100 lines</strong>. Your CTGradientElement.m should now be looking something like <a href="http://pub.lipidity.com/CTGradient/CTGradient3.m">this</a>. Going well, but let&#8217;s take things up a notch.</p>

<hr />

<p>For Trimmit&#8217;s background, we&#8217;re not interested in the red, green, blue and alpha components - we just need a grayscale shading. This is the most fun part.</p>

<p>Instead of <code>float red, green, blue, alpha;</code> in the CTGradientElement struct, we can have just <code>float shade;</code>.</p>

<p>Now, during <code>init</code> we have:</p>

<pre><code>CGFunctionCallbacks evaluationCallbackInfo = {0 , &amp;linearEvaluation, 0};
static const float input_value_range[2] = { 0, 1 };
static const float output_value_ranges[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
gradientFunction = CGFunctionCreate(&amp;elementList, 1, input_value_range, 4, output_value_ranges, &amp;evaluationCallbackInfo);
</code></pre>

<p>The third argument, <var>input_value_range</var> is the domain. This gets passed into linearEvalution through <var>*in</var>.This is the independent variable. When we&#8217;re drawing the gradient, linearEvaluation is called with <var>*in</var> (the domain) starting at the first value of <var>input_value_range</var> and ending up at the second. So, something like 0.000, 0.001, 0.002 &#8230; 0.998, 0.999, 1.000. The function&#8217;s job is to set the the color components for each given value of the domain.</p>

<p>The first optimization we can make here is to return only one channel instead of four. This changes it to:</p>

<pre><code>- (id)init {
    if (self = [super init]) {
        CGFunctionCallbacks evaluationCallbackInfo = {0, &amp;linearEvaluation, 0};
        static const float range[2] = {0, 1};
        static const float domain[2] = {0, 1};
        gradientFunction = CGFunctionCreate(&amp;elementList, 1, domain, 1, range, &amp;evaluationCallbackInfo);
    }
    return self;
}
</code></pre>

<p>This change impacts back on the linearEvaluation function - now it only needs to return one channel:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    CTGradientElement *color1 = *(CTGradientElement **)info;
    out[0] = (color1-&gt;nextElement-&gt;shade - color1-&gt;shade)*(*in) + color1-&gt;shade;
}
</code></pre>

<p>And don&#8217;t forget <code>+gradientWithBeginningColor:endingColor:</code>. We improve performance here, as we only need the shade - not a color. We can rename it to something appropriate.</p>

<pre><code>+ (id)gradientWithBeginningShade:(float)begin endingShade:(float)end {
    id newInstance = [[[self class] alloc] init];
    CTGradientElement color1, color2;

    color1.shade = begin; color2.shade = end;

    [newInstance addElement:&amp;color1];
    [newInstance addElement:&amp;color2];
    return [newInstance autorelease];
}
</code></pre>

<p>Now we&#8217;re only returning one grayscale channel. But hold on, we&#8217;re still in the RGB colorspace! That&#8217;s easily fixed. In <code>fillRect:</code>, replace:</p>

<pre><code>#if MAC_OS_X_VERSION_MAX_ALLOWED &gt;= MAC_OS_X_VERSION_10_4
    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
#else
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
#endif
</code></pre>

<p>with:</p>

<pre><code>CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
</code></pre>

<p class="note">CGColorSpaceCreateDeviceGray is device-dependent on Mac OS X 10.3 and below, but starting from Tiger, it&#8217;s now device-independent which is good in terms of appearance.</p>

<p>While we&#8217;re in <code>fillRect:</code>, we can also make a few more improvements:</p>

<pre><code>- (void)fillRect:(NSRect)rect {
    CGContextRef currentContext = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSaveGState(currentContext);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
    CGContextClipToRect(currentContext, *(CGRect *)&amp;rect);
    CGShadingRef myCGShading = CGShadingCreateAxial(colorspace, CGPointMake(0, 0), CGPointMake(0, NSMaxY(rect)), gradientFunction, 0, 0);
    CGContextDrawShading(currentContext, myCGShading);

    CGShadingRelease(myCGShading);
    CGColorSpaceRelease(colorspace);
    CGContextRestoreGState(currentContext);
}
</code></pre>

<p>I moved the startPoint and endPoint CGPoints straight into the CGShadingCreateAxial call. Also, we only ever fill the whole view with the gradient, so just put in <code>0</code> instead of using NSMinX and NSMinY. We could replace the <code>CGPointMake(0, 0)</code> with <code>(CGPoint){0,0}</code>, but I&#8217;m not sure if that&#8217;d be noticeably faster.</p>

<hr />

<p>Our code is at a lean <strong>80 lines</strong>. Now for the biggest change yet.</p>

<hr />

<p>Heading back to dear old linearEvaluation. Look at this line:</p>

<pre><code>out[0] = (color1-&gt;nextElement-&gt;shade - color1-&gt;shade)*(*in) + color1-&gt;shade;
</code></pre>

<p>What&#8217;s happening here? Think about it like this:</p>

<p>Essentially, we&#8217;re just &quot;graphing&quot; a straight line:</p>

<pre><code>y = mx + c
</code></pre>

<p>where <var>x</var> is the position, <var>*in</var>, and <var>y</var> is the shade we return (<var>out[0]</var>), and <var>c</var> is the initial shade.</p>

<p>Since our <var>x</var> value only goes from 0 to 1 (see domain in CGFunctionCreate), at <code>x = 0</code>, we will have <code>y = c</code>. At <code>x = 1</code>, we&#8217;ll have <code>y = m + c</code>.</p>

<p><img src='http://lipidity.com/wordpress/wp-content/uploads/2007/11/gradient-graph.png' alt='Graph of Gradient Function' class='feature' /></p>

<p><strong>So</strong> we only need the start shade as our <var>*info</var> value, since we can have <var>m</var> as the difference between the final and initial shades. Let&#8217;s effect this in our code.</p>

<p>We can get rid of the CTGradientElement struct. Remove from the header:</p>

<pre><code>typedef struct _CTGradientElement {
    float shade;
    struct _CTGradientElement *nextElement;
} CTGradientElement;
</code></pre>

<p>Instead of the struct, we&#8217;ll use a single <var>shade</var> instance variable. We don&#8217;t need the <code>+gradientWithBeginningShade:endingShade:</code> anymore, nor do we need <code>-addElement:</code>. So our interface now looks like this:</p>

<pre><code>@interface CTGradient : NSObject {
    float shade;
    CGFunctionRef gradientFunction;
}
- (void)fillRect:(NSRect)rect;
@end
</code></pre>

<p>From the implementation, we can remove the <code>free</code> calls in <code>dealloc</code> as well as the whole of <code>+gradientWithBeginningShade:endingShade:</code> and <code>addElement:</code>. We can set the <code>shade</code> in the init method (and replace <code>&amp;elementList</code> with <code>&amp;shade</code>), and change the linearEvaluation function to:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    out[0] = *(float*)info + (*in)*0.1;
}
</code></pre>

<p>The <code>0.1</code> is what determines how much brighter the top of the gradient is (it&#8217;s the <var>m</var> value of our straight line) compared to the bottom.</p>

<p><strong>But</strong> since the <code>(*in)*0.1</code> will go from <code>0</code> to <code>0.1</code> (as <var>*in</var> goes from 0 to 1), we can actually change the <code>domain</code> we declare for CGFunctionCreate to {0, 0.1} and have our function as:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    out[0] = *(float*)info + *in;
}
</code></pre>

<p>You can now add accessors for <code>shade</code> if you need to change the shade of the gradient or you could even have an <code>initWithShade:</code> method. In fact, here&#8217;s an Xcode project with the gradient.</p>

<p class="download"><a href="http://pub.lipidity.com/CTGradient/GradientSample.tar.bz2">Lean Gradient Xcode Project</a></p>

<p>We now have our gradient code down <big>from <strong>1300 lines</strong> to just over <strong>30 lines</strong></big>.</p>

<hr />

<p>We&#8217;ve almost reached a similar level of optimization to Trimmit&#8217;s gradient. There will be further optimizations you can make, but it depends on what you&#8217;re using the gradient for. For example, if the gradient you&#8217;re drawing is always the same, you can optimize further by removing the <code>shade</code> instance variable and all references to it, and hardcode the value into the linearEvaluation function.</p>

<p>Getting to the end of this article, you&#8217;re probably thinking that it would be a bit of a waste to use CTGradient if by the time you optimize it for your application, it doesn&#8217;t resemble the original at all. And you&#8217;re quite right. The documentation already shows you <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_shadings/chapter_9_section_6.html">how to draw gradients</a>, yet the number of applications using CTGradient - the whole 1300 lines of it - is astonishing.</p>

<p>Please: When you use other people&#8217;s code, don&#8217;t put it in without a thought. Go through it, understand it, and optimize it for your specific need. For the better performance and reduced RAM usage, computers will thank you.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/ctgradient-code-bloat/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting things done with style</title>
		<link>http://lipidity.com/apple/gtd-inbox-core-graphics/</link>
		<comments>http://lipidity.com/apple/gtd-inbox-core-graphics/#comments</comments>
		<pubDate>Mon, 27 Aug 2007 03:50:33 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Review]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/gtd-inbox-core-graphics</guid>
		<description><![CDATA[In the world of GTD, Midnight Inbox is surely one of the best designed contenders. It&#8217;s so good it&#8217;s addictive.



I&#8217;ve recently started using Inbox for organizing and collecting all my various projects as well as study materials and schedules. Although it took a while for me to get used to the whole GTD concept, I [...]]]></description>
			<content:encoded><![CDATA[<p>In the world of <acronym title='Getting Things Done'>GTD</acronym>, <a href="http://midnightbeep.com/">Midnight Inbox</a> is surely one of the best designed contenders. It&#8217;s so good it&#8217;s addictive.</p>

<!--more-->

<p>I&#8217;ve recently started using Inbox for organizing and collecting all my various projects as well as study materials and schedules. Although it took a while for me to get used to the whole <acronym title='Getting Things Done'>GTD</acronym> concept, I now use the application constantly.</p>

<p class='centre'>
<img oldsrc="http://lipidity.com/images/Midnight_Inbox-20070827-133833.jpg" src="http://lipidity.com/images/Inbox-20070826-130315.jpg" alt="[Midnight Inbox]" title="Screenshot of the Midnight Inbox app Work screen" width="275" height="211" class='feature' /><br />
<small>Midnight Inbox implements David Allen&#8217;s <acronym title='Getting Things Done'>GTD</acronym> approach</small>
</p>

<p>One of the great things about Inbox is that it looks so good. Good enough to forgive make up for its relatively frequent crashes. The interface is really well designed, keeping in line with many of the Mac metaphors while adding a few unobtrusive features that are generally easy to work out.</p>

<p>It&#8217;s clear this is a great application. It has major potential and <a href="http://www.midnightbeep.com/blog/?p=117">version 2.0</a> looks exciting. Congrats to the developers.</p>

<hr />

<p>Going through the contents of the application, I found CGS.framework and thought, &#8220;Interesting. They&#8217;re using Core Graphics&#8221;. It didn&#8217;t occur to me that I released a framework with the exact same name. Well, I&#8217;ve finally realized that one of my favorite apps is possibly using <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource">this framework</a> and &#8230; [speechless].</p>

<p>This is the first application (to my knowledge) to use that particular framework, and only the second to use code that I&#8217;ve posted. (Logan Rockmore&#8217;s <a href="http://www.loganrockmore.com/AssignmentPlanner/">Assignment Planner</a> was the first, using the <a href="http://dev.lipidity.com/apple/core-graphics-meet-core-image-demo-app">AnimatingTabView</a>).</p>

<hr />

<p>I&#8217;ve never used another GTD program before, but after trying this app, I doubt I&#8217;ll need to. Go check out the fantabulous <a href="http://midnightbeep.com/">Midnight Inbox</a> and get things done with style.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/gtd-inbox-core-graphics/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Cocoa Animation Effects</title>
		<link>http://lipidity.com/apple/cocoa-transition-animation-effects-video/</link>
		<comments>http://lipidity.com/apple/cocoa-transition-animation-effects-video/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 06:15:19 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Animation]]></category>

		<category><![CDATA[core-image]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[GUI]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Screencast]]></category>

		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/cocoa-transition-animation-effects-video</guid>
		<description><![CDATA[I wrote this app about 8 months ago, and it&#8217;s managed to find itself on Youtube.







It uses Core Graphics and Core Image APIs for the transition effects to animate the window / view, which probably needs a minimum of Mac OS X Tiger. The full source code is available.
]]></description>
			<content:encoded><![CDATA[<p>I wrote this app about 8 months ago, and it&#8217;s managed to find itself on Youtube.</p>

<!--more-->

<div class='centre'>
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/FSUu_a_f88c&#038;rel=0"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/FSUu_a_f88c&#038;rel=0" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object>
</div>

<p>It uses Core Graphics and Core Image APIs for the transition effects to animate the window / view, which probably needs a minimum of Mac OS X Tiger. The <a href='http://dev.lipidity.com/apple/core-graphics-meet-core-image-demo-app' title='Core Graphics Image Transition Animation Effects'>full source code</a> is available.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/cocoa-transition-animation-effects-video/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Secret Quicksilver animation effects</title>
		<link>http://lipidity.com/apple/quicksilver-animation-effects/</link>
		<comments>http://lipidity.com/apple/quicksilver-animation-effects/#comments</comments>
		<pubDate>Wed, 20 Jun 2007 02:00:14 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Quicksilver]]></category>

		<category><![CDATA[Animation]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[GUI]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[plugin]]></category>

		<category><![CDATA[Tutorial]]></category>

		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/quicksilver-animation-effects</guid>
		<description><![CDATA[You may have had a shot at creating a Quicksilver interface. (If you haven't, see <a href="http://dev.lipidity.com/feature/tutorial/quicksilver-interface-tutorial">the tutorial</a>). While it's good fun to play with changing the colors and positions of the controls, there is a whole lot of really clever code in Quicksilver that lets you go beyond that and play with some weird and wacky effects on <em>any</em> window.]]></description>
			<content:encoded><![CDATA[<p class="centre"><a rel="lightbox" href="http://dev.lipidity.com/wp-content/uploads/2007/06/quicksilver-cube-animation.png" title="Mac Cube Transition Effect"><img alt="[Quicksilver Cube Effect]" title="Image of Core Graphics cube transition effect" src="http://dev.lipidity.com/wp-content/uploads/2007/06/quicksilver-cube-effect.png" class="feature" width="292" height="233" /></a><br /><small>Quicksilver is capable of some very futuristic transition effects</small></p>

<h2>Standard Animation Effects</h2>

<p>Quicksilver adds a category to the NSWindow class to allow for some pretty cool effects.
The following should be pretty self-explanatory:</p>

<pre><code>-(void)pulse:(id)sender;
-(void)flare:(id)sender;
-(void)shrink:(id)sender;
-(void)fold:(id)sender;
</code></pre>

<p>What these methods essentially mean, is that you can pulse, flare, shrink or fold <em>any window</em> you have a reference to in a plugin - whether it&#8217;s an interface or dialog or something completely different. Eg, just call <code>[window shrink:nil]</code> and watch that NSWindow shrink down to nothing, or <code>[window flare:nil]</code> to make it burst away!</p>

<h2>Private Core Graphics Animations</h2>

<p>Quicksilver also adds methods to use private <a href="http://dev.lipidity.com/feature/tutorial/xcode-transitions-core-graphics-image-2" title="Core Graphics Transitions Tutorial">Core Graphics transitions</a> for instances of NSWindow or its subclasses. The main method is defined something like:</p>

<pre><code>- (void) displayWithTransition:(CGSTransitionType)type option:(CGSTransitionOption)option duration:(float)duration;
</code></pre>

<p>The transitions you have access to are fade, zoom, reveal, slide, warp-fade, swap, warp-switch and the famous cube animation. You can use them on any window, for example:</p>

<pre><code>[window displayWithTransition:CGSCube option:CGSLeft duration:1.3];
</code></pre>

<p>To learn more about Core Graphics transitions, see the <a href="http://dev.lipidity.com/feature/tutorial/ebook-xcode-animations-core-graphics" title="Core Graphics Animations and Transitions Tutorial">Core Graphics ebook</a>, or play around with the <a href="http://dev.lipidity.com/apple/core-transitions-framework" title="Core Graphics and Core Image transition animations">Core Transitions Framework</a>.</p>

<p class="yellow_note">Quicksilver&#8217;s CGSPrivate.h file is missing CGSFlip, but you can run the Dashboard-style flip effect by using the integer 9.</p>

<h2>Quicksilver&#8217;s own animations</h2>

<p>Alcor has used various techniques to write several very interesting animation effects into Quicksilver. You&#8217;ll be familiar with some of these (just watch the Primer interface activate and deactivate) but for whatever reason, many of these bizarre animations never made into an interface. They&#8217;re really very clever. I&#8217;ve played around with some of these:</p>

<ul>
<li>QSGrowEffect</li>
<li>QSShrinkEffect</li>
<li>QSSlightGrowEffect</li>
<li>QSSlightShrinkEffect</li>
<li>QSBingeEffect</li>
<li>QSPurgeEffect</li>
<li>QSExplodeEffect</li>
<li>QSExtraExtraEffect</li>
<li>QSShakeItLikeAPolaroidPictureEffect</li>
<li>QSBoobTubeEffect</li>
<li>QSVExpandEffect</li>
<li>QSVillainousKryptonianEffect</li>
<li>QSMMBlowEffect</li>
<li>QSLudicrousSpeedEffect</li>
</ul>

<p>Very interesting to look at, but how does one use these effects?</p>

<p>As we are dealing with Quicksilver, the solution is (as expected) very elegant. There are very simple methods to set a show, hide or execute effect for a window. These methods don&#8217;t even require an explanation; they&#8217;re so simple:</p>

<pre><code>// Effect for showing the QSWindow
[window setShowEffect:[NSDictionary dictionaryWithObjectsAndKeys:@&quot;QSSlightGrowEffect&quot;,@&quot;transformFn&quot;,@&quot;show&quot;,@&quot;type&quot;,[NSNumber numberWithFloat:2.0],@&quot;duration&quot;,nil]];

// Effect for hiding the QSWindow
[window setHideEffect:[NSDictionary dictionaryWithObjectsAndKeys:@&quot;QSSlightShrinkEffect&quot;,@&quot;transformFn&quot;,@&quot;hide&quot;,@&quot;type&quot;,[NSNumber numberWithFloat:2.0],@&quot;duration&quot;,nil]];

// The "execute" effect is slightly different:
[window setWindowProperty:[NSDictionary dictionaryWithObjectsAndKeys:@&quot;QSExplodeEffect&quot;,@&quot;transformFn&quot;,@&quot;hide&quot;,@&quot;type&quot;,[NSNumber numberWithFloat:1.5],@&quot;duration&quot;,nil] forKey:kQSWindowExecEffect];</code></pre>

<p>Easy!</p>

<h2>Sample plugin</h2>

<p><a href="http://dev.lipidity.com/wp-content/uploads/2007/06/effects.zip" title="Download Quicksilver Effects Plugin"><img class="fright" src="http://qs.lipidity.com/fumo/QSPlugin.png" title="Quicksilver Plugin Icon" alt="[Plugin Icon]" height="128" width="128" /></a> 
I don&#8217;t dare mention all this private goodness and not even provide a demonstration. I&#8217;ve created an &#8220;Effects&#8221; plugin that will allow you to change the activate, deactivate and execute effects for <em>any</em> Quicksilver interface temporarily to play around with the effects. Just for good measure, I&#8217;ve also thrown in an action that lets you explore Core Graphics transitions as well.</p>

<p>This is not really a bona fide Quicksilver plugin; while it does let you have some fun with the effects, it&#8217;s not very user-friendly and doesn&#8217;t save your configuration. 
If these animations prove to be popular, then I&#8217;ll write a proper plugin to let you configure the effects more easily (probably through a preference pane) and remembers your settings.</p>

<p class="download"><a href="http://dev.lipidity.com/wp-content/uploads/2007/06/effects.zip" title="Download Quicksilver Effects Plugin">Download Quicksilver Effects Plugin</a></p>

<h4>Usage</h4>

<p>Type in the name of the effect you want, then use &#8220;Set Hide Effect&#8221;, &#8220;Set Show Effect&#8221; or the &#8220;Set Exec Effect&#8221; action. The list of effects is given <a href="#toc-quicksilvers-own-animations">above</a>; just type one in and run the relevant action.</p>

<p>To run a Core Graphics transition, type in the name of the transition, and use the &#8220;Run CoreGraphics Transition&#8221; action. You can optionally specify a direction in the indirect selector. (You can enter text in the direct and indirect selectors by pressing the period &#8220;.&#8221; key)</p>

<h4>For example</h4>

<ul>
<li><big>&#8220;QSBingeEffect&#8221; -&gt; Set Show Effect</big></li>
<li><big>&#8220;QSPurgeEffect&#8221; -&gt; Set Hide Effect</big></li>
<li><big>&#8220;QSExplodeEffect&#8221; -&gt; Set Exec Effect</big></li>
<li><big>&#8220;flip&#8221; -&gt; Run CoreGraphics Transition</big></li>
<li><big>&#8220;slide&#8221; -&gt; Run CoreGraphics Transition -&gt; &#8220;up&#8221;</big></li>
<li><big>&#8220;swap&#8221; -&gt; Run CoreGraphics Transition -&gt; &#8220;inout&#8221;</big></li>
</ul>

<p class="centre">
<a rel="lightbox[demo]" href='http://dev.lipidity.com/wp-content/uploads/2007/06/set-show-effect.png' title='Set Show Effect'><img src='http://dev.lipidity.com/wp-content/uploads/2007/06/set-show-effect.thumbnail.png' alt='Set Show Effect' width='108' height='128' /></a>
<a rel="lightbox[demo]" href='http://dev.lipidity.com/wp-content/uploads/2007/06/set-hide-effect.png' title='Set Hide Effect'><img src='http://dev.lipidity.com/wp-content/uploads/2007/06/set-hide-effect.thumbnail.png' alt='Set Hide Effect' width='108' height='128' /></a>
<a rel="lightbox[demo]" href='http://dev.lipidity.com/wp-content/uploads/2007/06/set-exec-effect.png' title='Set Exec Effect'><img src='http://dev.lipidity.com/wp-content/uploads/2007/06/set-exec-effect.thumbnail.png' alt='Set Exec Effect' width='106' height='128' /></a>
<a rel="lightbox[demo]" href='http://dev.lipidity.com/wp-content/uploads/2007/06/core-graphics-cube.png' title='Core Graphics Cube Effect'><img src='http://dev.lipidity.com/wp-content/uploads/2007/06/core-graphics-cube.thumbnail.png' alt='Core Graphics Cube Effect' width='105' height='128' /></a>
<a rel="lightbox[demo]" href='http://dev.lipidity.com/wp-content/uploads/2007/06/core-graphics-swap-effect.png' title='Core Graphics Swap Effect'><img src='http://dev.lipidity.com/wp-content/uploads/2007/06/core-graphics-swap-effect.thumbnail.png' alt='Core Graphics Swap Effect' width='92' height='128' /></a><br />
<small>Pictures show how to use the effects plugin. Actual animations are not shown.</small>
</p>

<hr />

<p>Quicksilver has many such hidden surprises and nifty time-saving methods; it&#8217;s so well thought out and full of these amazing gems!</p>

<p>What do you think about these animations? Be sure to let me know if you&#8217;d like a proper, more user-friendly plugin to use these effects.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/quicksilver-animation-effects/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Warp, bend, squeeze and transform windows with CGSSetWindowWarp</title>
		<link>http://lipidity.com/apple/warp-bend-squeeze-and-transform-windows-with-cgssetwindowwarp/</link>
		<comments>http://lipidity.com/apple/warp-bend-squeeze-and-transform-windows-with-cgssetwindowwarp/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 08:40:38 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Animation]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Source Code]]></category>

		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/warp-bend-squeeze-and-transform-windows-with-cgssetwindowwarp</guid>
		<description><![CDATA[How would you like to have the power to squish, warp and transform windows to your liking? With the private Core Graphics function CGSSetWindowWarp, you can!]]></description>
			<content:encoded><![CDATA[<p><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/Warped.png" style="width: 100%" title="Warped clocks" alt="Warped clocks" /></p>

<p>The function CGSSetWindowWarp is part of the private portion of <a href="http://dev.lipidity.com/feature/tutorial/ebook-xcode-animations-core-graphics" title="Core Graphics tutorial ebook">Core Graphics</a>. Although its just as obscure and undocumented as the rest of the <ins>private parts of the</ins> framework, there has been some discovery and progress into its <a href="http://kevin.sb.org/articles/2006/07/23/cgssetwindowwarp-explained" rel="external">usage</a>.  Erling Ellingsen has written (a while ago) about CGSSetWindowWarp on <a href="http://blog.medallia.com/2006/05/windowwarp.html" rel="external">his blog</a>, and he also shows some very interesting screenshots of what&#8217;s possible.</p>

<p><img src="http://blog.medallia.com/images/warp/full-3d-fancy-thumb.jpg" alt="transformed windows" /><img src="http://blog.medallia.com/images/warp/full-3d-slash-thumb.jpg" alt="transformed windows" /></p>

<p>So, how do you use this incredible function in your Cocoa (<a href="http://paste.lisp.org/display/2717">or Carbon</a>) application?
<!--more--></p>

<h2>CGSSetWindowWarp Usage</h2>

<h3>Including the header</h3>

<p>Whenever you use private Core Graphics functions, you generally need to <code>#import </code> either one of CoreGraphicsServices.h or CGSPrivate.h (available for download with my <a href="http://dev.lipidity.com/feature/tutorial/ebook-xcode-animations-core-graphics" title="Core Graphics tutorial ebook">Core Graphics ebook</a>). However, if you&#8217;re not interested in using the rest of the Core Graphics API, you can get away with simply adding the following to your main class&#8217; header file:</p>

<pre class="code"><code>
typedef struct CGPointWarp {
        CGPoint local;
        CGPoint global;
}CGPointWarp;

typedef int CGSConnectionID;
typedef int CGSWindowID;

extern CGSConnectionID _CGSDefaultConnection();

extern CGError CGSSetWindowWarp(CGSConnectionID, CGSWindowID, int w, int h, CGPointWarp mesh[w][h]);
extern OSStatus CGSGetScreenRectForWindow(CGSConnectionID cid, CGSWindowID wid, CGRect *outRect);
extern OSStatus CGSGetWindowBounds(CGSConnectionID cid, CGSWindowID wid, CGRect *bounds);</code></pre>

<p>As you&#8217;ve probably guessed, the function that actually applies the mesh transform is <code>CGSSetWindowWarp</code>. You can create a mesh in two different ways.</p>

<h3>Creating the mesh</h3>

<p>To create a mesh, we need to specify how many points we&#8217;re going to take for our grid length-wise and width-wise. Something like this:</p>

<pre class="code"><code>#define H 64
#define W 5</code></pre>

<p>We&#8217;ll also need to refer to the position and size of the frame so the following code in the method you&#8217;re writing this will give us access to the frame of the NSWindow:</p>

<pre class="code"><code>CGRect frame;
CGSGetWindowBounds(cid, [window windowNumber], &amp;frame);</code></pre>

<p>The use of CGSGetWindowBounds ensures we get the apparent frame rather than just the frame computed by our code as we&#8217;ll be applying various transformations.</p>

<p>The first way to create a mesh requires more labor (yes, its tiring to code) but gives you greater control over the mesh and the transformations applied to the NSWindow.</p>

<h4>Manual mesh</h4>

<pre class="code"><code>CGPointWarp meshes[H][W] =
{
{ {{0, 0},{10, 10}}, {{200,0},{180,12}} },
{ {{0, 50},{0,50}}, {{200,50},{200,50}} },
{ {{0,100},{0,100}}, {{200,100},{200,100}} },
{ {{0,150},{0,150}}, {{200,150},{200,150}} },
{ {{0,200},{0,200}}, {{200,200},{200,200}} },
};</code></pre>

<p>Here, you specify firstly the coordinates of the point which you&#8217;re taking, and where you want to move that point. The first line in the above code takes (0,0) and moves it to (10,10) and moves (200,0) to (180,12). However, the first set of coordinates are local coordinates, and the second set are global. (ie., the first set are on the plane of the window, while the second set use the screen as the plane. This is to allow the window to be stretched out beyond the scope of the current frame.) We could solve this issue by using:</p>

<pre class="code"><code>
int x = frame.origin.x;
int y = frame.origin.y;
CGPointWarp meshes2[H][W] =
{
{ {{0, 0},{x, y}}, {{200,0},{x+200,y}} },
{ {{0, 50},{x,y+50}}, {{200,50},{x+200,y+50}} },
{ {{0,100},{x,y+100}}, {{200,100},{x+200,y+100}} },
{ {{0,150},{x,y+150}}, {{200,150},{x+200,y+150}} },
{ {{0,200},{x,y+200}}, {{200,200},{x+200,y+200}} },
};</code></pre>

<p>The preceding code just warps the window of size 200&#215;200 to its current position so no change is observable. If we wanted to stretch out the middle of the window horizontally, we could use a mesh in the form:</p>

<pre class="code"><code>
int x = frame.origin.x;
int y = frame.origin.y;
CGPointWarp stretchThroughMiddleMesh[H][W] =
{
{ {{0, 0},{x, y}}, {{200,0},{x+200,y}} },
{ {{0, 50},{x-10,y+50}}, {{200,50},{x+200+10,y+50}} },
{ {{0,100},{x-20,y+100}}, {{200,100},{x+200+20,y+100}} },
{ {{0,150},{x-10,y+150}}, {{200,150},{x+200+10,y+150}} },
{ {{0,200},{x,y+200}}, {{200,200},{x+200+10,y+200}} },
};</code></pre>

<p>We&#8217;ve taken the side where x=0 and moved x further back along the middle, and done the opposite on the opposite side (where x=200). This results in the NSWindow being warped to have a bulge in the middle.
<a href="http://dev.lipidity.com/wp-content/uploads/2007/02/warpbulge.png" title="warp bulge" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warpbulge.thumbnail.png" alt="warp bulge" /></a></p>

<p>Again, this would only look like the screenshot on a window with a height and width of 200. For a window that&#8217;s a different size, you&#8217;ll need to change the values to match the height and width of the window. For the y-values in the mesh (x, x+50, x+100, etc. in the different rows), the numbers are determined by how many points you&#8217;ve taken (your value for <var>H</var>) and the width of the window. The general formula you would use would be <code>x + ( frame.size.height / (W-1) )</code>. You&#8217;ll see this more clearly in the second method.</p>

<h4>Mesh through iterative formulae</h4>

<p>The second method to create a mesh is to run a loop to configure your individual points. Here&#8217;s a basic example that creates a mesh that would be identical to the current state of the window:</p>

<pre class="code"><code>
int h;
int w;
CGPointWarp meshes[H][W];
for (h = 0; h &lt; H; h++) {
    for (w = 0; w &lt; W; w++) {
        CGPointWarp point;
        point.local.x = w * (frame.size.width / (W - 1));
        point.local.y = h * (frame.size.height / (H - 1));
        point.global.x = point.local.x + frame.origin.x;
        point.global.y = point.local.y + frame.origin.y;

        meshes[h][w] = point;
    }
}</code></pre>

<p>Obviously we want to transform the window somehow. We need to apply some sort of mathematical function to the points to make them deviate from their original positions or coordinates. (This is the part where you start to wish you&#8217;d paid more attention in math class).</p>

<p>Lets say we want to skew the window using the x-axis. Each successive x-value needs to be greater than the previous one. Since we&#8217;re looping through each point, at any time in the inner for loop, the values of the current point are (w,h). (In <a href="http://www.google.com/search?q=Cartesian+coordinates">Cartesian coordinates</a> the x value is first, followed by the y value) In order to increase each successive value for x, we need to add something. But, we need to add more than what we did the previous time. The easiest way to do this without adding any new variables is to use the value that we&#8217;re incrementing each time - the x value itself. So, for a skewed window, we have the following mesh:</p>

<pre class="code"><code>
int h;
int w;
CGPointWarp meshes[H][W];
for (h = 0; h &lt; H; h++) {
    for (w = 0; w &lt; W; w++) {
        CGPointWarp point;
        point.local.x = w * (frame.size.width / (W - 1));
        point.local.y = h * (frame.size.height / (H - 1));
        point.global.x = point.local.x + frame.origin.x + <span style="color: black">15*h</span>;
        point.global.y = point.local.y + frame.origin.y;

        meshes[h][w] = point;
    }
}</code></pre>

<p>The skewed window would like this when the mesh was applied:
<a href="http://dev.lipidity.com/wp-content/uploads/2007/02/skew.png" title="Skews CGSWarp" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/skew.thumbnail.png" alt="Skews CGSWarp" /></a></p>

<h3>Applying the mesh</h3>

<p>The transform mesh was really the hard part. Applying the transformation mesh (or grid) to a window is as easy as:</p>

<pre class="code"><code>
CGSSetWindowWarp(_CGSDefaultConnection(), [window windowNumber], W, H, meshes);</code></pre>

<p>The possibilities of this are really amazing. I&#8217;ve always wanted to write an NSWindow subclass that bent and reduced in opacity as it was dragged, imitating <a href="http://static.flickr.com/72/221355329_a7dc022e74.jpg" rel="external">XGL</a>. With CGSSetWindowWarp and Core Graphics, I&#8217;m sure it&#8217;ll be a breeze. Or what about an virtual universe-style Finder cross Desktop, sort of like <a href="http://www.acm.uiuc.edu/macwarriors/projects/oldprojects/3dosx/screenshots.html" rel="external">3DOSX</a>? You could even imitate other effects with this, such as the cube, but still get live updating in your windows - a limitation present in the Core Graphics transition effects.</p>

<p>For a source code, and a further explanation, see Kevin Ballard&#8217;s post on the subject of <a href="http://kevin.sb.org/articles/2006/07/23/cgssetwindowwarp-explained" rel="external">CGSSetWindowWarp</a>.</p>

<p><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/right.png" title="Warped clocks" alt="Warped using CGSSetWindowWarp" /><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/squish.png" title="Warped clocks" alt="Warped clocks" /><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/left.png" title="Warped clocks" alt="Warped clocks" /></p>

<p><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/control.png" title="Warped clocks" alt="Warped clocks" /><img src="http://dev.lipidity.com/wp-content/uploads/2007/02/warps/blur.png" title="Warped clocks" alt="Warped clocks" /></p>

<p>Did you find this useful? Or do you have any other method that you use for eye candy?</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/warp-bend-squeeze-and-transform-windows-with-cgssetwindowwarp/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Unleashing the Mac OS X Genie</title>
		<link>http://lipidity.com/apple/unleashing-the-mac-os-x-genie/</link>
		<comments>http://lipidity.com/apple/unleashing-the-mac-os-x-genie/#comments</comments>
		<pubDate>Wed, 22 Nov 2006 11:52:13 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Animation]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Source Code]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/unleashing-the-mac-os-x-genie</guid>
		<description><![CDATA[How to use the genie effect in Cocoa with undocumented Core Graphics functions.]]></description>
			<content:encoded><![CDATA[<p><img src="http://dev.lipidity.com/wp-content/uploads/2006/11/genie.jpg" alt="Genie animation" /><br />
</p>

<p>
Look familiar? The Mac OS X genie effect is a <a rel="external" href="http://www.appleinsider.com/article.php?id=680" title="View information about the genie effect and Apple's patent on it.">patented</a> effect that is set as the default minimizing effect for windows in the Mac environment. Dating back to 2004, this animation involves a complex transformation of the source window in order to render it correctly on screen. Apple have not documented this feature for use in third party applications in Cocoa (<a href="https://developer.apple.com/documentation/Carbon/Reference/Window_Manager/Reference/reference.html#//apple_ref/c/func/TransitionWindow">It is available in Carbon</a>). It is something else that makes up the private portion of the <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource" title="View my CGS framework which opens up a lot of the undocumented portions of Core Graphics.">Core Graphics framework</a>. However, keen developers like yourself can play with / use / abuse this awesome effect all you like.
</p>

<p>
The genie effect can be run using the private Core Graphics function <code>CGSCreateGenieWindowAnimation</code>. The requisites for this: A window to use the effect on, a connection to Core Graphics, and another window into which the source window goes. As an example, take a look at this code:</p>

<pre><code>- (void)doGenieFrom:(NSWindow*)source to:(NSWindow*)destination backwards:(BOOL)backwards {
    CGSAnimationRef ref;
    int err;

    err = CGSCreateGenieWindowAnimation(_CGSDefaultConnection(), [source windowNumber], [destination windowNumber], &#038;ref);

    if (backwards) {
        [source orderWindow:NSWindowBelow relativeTo:[destination windowNumber]]; /* No different to makeKeyAndOrderFront]*////
        [source setExcludedFromWindowsMenu:NO];
        [source flushWindow];
    }    
    
    if (0 == err) {
        float x;
        
        for (x = (backwards ? 1.0 : 0.0); (backwards ? (x &gt;= 0.0) : (x &lt;= 1.0)); (backwards ? (x -= 0.01) : (x += 0.01))) {            
            err = CGSSetWindowAnimationProgress(ref, x);
            
            usleep(1000);
        }
        
        err = CGSReleaseWindowAnimation(ref);
        
    }
    
    if (backwards) {
        [destination setExcludedFromWindowsMenu:YES];
    [source makeKeyAndOrderFront:self];
        [source setExcludedFromWindowsMenu:NO];
    } else {
        [source setExcludedFromWindowsMenu:YES];
        
        [destination makeKeyAndOrderFront:self];
        [destination setExcludedFromWindowsMenu:NO];
    }
}
</code></pre>

<p>How easy is that? Of course, this only compiles if you #import a header file that defines the Core Graphics private functions. (ie, just add <a href="http://dev.lipidity.com/wp-content/uploads/2006/11/coregraphicsservices.h">this file</a> to your Xcode project, then add a #import &#8220;coregraphicsservices.h&#8221; line at the top of the page where you want to use private CGS functions).</p>

<p><a class="imagelink" href="http://dev.lipidity.com/wp-content/uploads/2006/11/picture-1.png" title="Genie Effect via Framework" rel="lightbox"><img id="image67" src="http://dev.lipidity.com/wp-content/uploads/2006/11/picture-1.thumbnail.png" alt="Genie Effect via Framework" /></a></p>

<p>In the age of <a href="http://dev.lipidity.com/apple/passive-smokin">smoking windows</a>, <a href="http://dev.lipidity.com/apple/core-graphics-meet-core-image-demo-app">flashing views</a> and an unofficial <a href="http://dev.lipidity.com/apple/ilife-controls-hud-windows-and-more">redefinement of the <acronym title="Human Interface Guidelines">HIG</acronym></a> by developers, the genie animation can finally come out to play.</p>

<p>If you&#8217;re enthralled by the genie, here is a list of <a rel="external" href="http://www.silvermac.com/2006/minimising-windows-osx/">cool stuff you can do</a> on your mac regarding minimizing windows / expose.</p>

<p>Thoughts about this post? Add a comment, I value your feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/unleashing-the-mac-os-x-genie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>eBook: Xcode animations - Core Graphics</title>
		<link>http://lipidity.com/apple/ebook-xcode-animations-core-graphics/</link>
		<comments>http://lipidity.com/apple/ebook-xcode-animations-core-graphics/#comments</comments>
		<pubDate>Mon, 20 Nov 2006 08:54:42 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Animation]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[ebook]]></category>

		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/ebook-xcode-animations-core-graphics</guid>
		<description><![CDATA[

Play with fire.

Download

Feedback and criticism encouraged and appreciated.

&#169; 2006 Ankur Kothari
]]></description>
			<content:encoded><![CDATA[<p class='centre'><a title="Download the Xcode animations and transitions eBook" href="http://pub.lipidity.com/CG-ebook1.tar.bz2"><img id="image64" src="http://dev.lipidity.com/wp-content/uploads/2006/11/ebook1.png" alt="eBook 1" style='margin-top:12px;' class='feature' /></a></p>

<p>Play with fire.</p>

<p class="download"><a href="http://pub.lipidity.com/CG-ebook1.tar.bz2" title="Download the Xcode animations and transitions eBook">Download</a></p>

<p>Feedback and criticism encouraged and appreciated.</p>

<p>&copy; 2006 Ankur Kothari</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/ebook-xcode-animations-core-graphics/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CGS Framework now Universal! Tremendous power&#8230;</title>
		<link>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/</link>
		<comments>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/#comments</comments>
		<pubDate>Mon, 30 Oct 2006 12:18:45 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/cgs-framework-now-universal-tremendous-power</guid>
		<description><![CDATA[The fabled Core Graphics Framework is now released!

All the PPC / Intel specific bugs have been found, caught, and eradicated. The framework should now be ready for developer consumption for use in commercial apps, or for experimentation and utter bewilderment. Be amazed. Be very amazed, and download the framework straight from here or read and [...]]]></description>
			<content:encoded><![CDATA[<p class="callout">The fabled <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource" title="The Core Graphics Framework for everything Core Graphics.">Core Graphics Framework</a> is now released!</p>

<p>All the PPC / Intel specific bugs have been found, caught, and eradicated. The framework should now be ready for developer consumption for use in commercial apps, or for experimentation and utter bewilderment. <strong>Be amazed</strong>. Be very amazed, and download the framework straight from <a href="http://pub.lipidity.com/CGSFramework.tar.bz2" title="Download the Core Graphics framework straight away (direct link)">here</a> or read and download it from <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource" title="The Core Graphics Framework for everything Core Graphics.">the original post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The ultimate Core Graphics resource</title>
		<link>http://lipidity.com/apple/the-ultimate-core-graphics-resource/</link>
		<comments>http://lipidity.com/apple/the-ultimate-core-graphics-resource/#comments</comments>
		<pubDate>Fri, 27 Oct 2006 13:39:37 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[CoreGraphics]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource</guid>
		<description><![CDATA[Liberate your application

Now works on all architectures, and without hiccups!

Can&#8217;t get enough of window transitions? Love a little eye candy? Well, you&#8217;re in luck. The Core Graphics Framework and Xcode Project Template make adding the fantastic Core Graphics function to your app a breeze. In fact, it&#8217;s even more complete than the tutorial, and already [...]]]></description>
			<content:encoded><![CDATA[<h2>Liberate your application</h2>

<p class="blue_hilite">Now works on all architectures, and without hiccups!</p>

<p>Can&#8217;t get enough of window transitions? Love a little eye candy? Well, you&#8217;re in luck. The Core Graphics Framework and Xcode Project Template make adding the fantastic Core Graphics function to your app a breeze. In fact, it&#8217;s even more complete than the <a href="http://dev.lipidity.com/tutorial/xcode-transitions-core-graphics-image-2" title="The complete Core Graphics tutorial for beginners">tutorial</a>, and already has more features in it before you write a single line of code! It doesn&#8217;t stop there, however. This framework powerful enough to use the <strong>genie effect</strong>. That&#8217;s right. That awesome Mac OS X transform you can get when you minimize an application. Core Graphics contains a wealth of resources. You really have to check it out.</p>

<!--more-->

<h3>Point. Click. Zoom!</h3>

<p>The <acronym title="Core Graphics">CGS</acronym> Framework is a an implementation of transitions, transforms and everything Core Graphics. It includes the definitions and implementations for the methods, so that using a transition or transform is as simple as calling a single method! For example, scaling a window is as simple as a &#8220;- scale: about:&#8221; call on the window, and rotating it just requires a single &#8220;- rotate: about:&#8221;. In the same way, Core Graphics is laid bare with this framework, for you to utilize at your pleasure!</p>

<h3>Don&#39;t lift a finger</h3>

<p>The framework does all the work for you, but even then, it gets simpler. Source for a  sample app is included which means that you can create Core Graphics projects straight away by building on top of it. This saves you, the developer time in adding and linking the Framework, and reading and implementing the Core Graphics class in Interface Builder, as well as adding the framework to your project. A single double-click on the sample project and it&#8217;s all done for you. What more could you ask? Download a copy and check it out today. You&#8217;ll be surprised how powerful it is.</p>

<h3>Gimme already!</h3>

<p><strong>Now a universal binary for your developing pleasure!</strong></p>

<p class="download"><a id="p23" href="http://pub.lipidity.com/CoreGFX.tar.bz2" title="CGS Framework / Project">CGS Framework + Sample App</a></p>

<p>Once downloaded, open CoreGFX.app to view some of the possible effects. You can copy the source folder to hard drive if you need to build a Core Graphics enabled app. Enjoy the wonderfulness, and I hope you have fun!</p>

<hr />

<p>Any queries, <a title="Jump straight to the comment form to leave a reply." href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource#comment-form">fire away.</a> </p>

<p>Make sure you understand that some of the functions of Core Graphics used in this framework are undocumented, internal APIs that Apple haven&#8217;t released. (Calm down. It&#8217;s not illegal). Having said that, apps like <a href="http://quicksilver.blacktree.com/" title="Quicksilver is an essential application for Mac OS X. It is a lot more than an application launcher; it gives you control over your entire Mac and will definitely increase your productivity. The eye candy is great too, courtesy of Core Graphics.">Quicksilver</a> would be quite bland without the use of the undocumented Core Graphics functions, so exercise your discretion.</p>

<p>This project relies heavily on work by <a href="http://homepage.cs.latrobe.edu.au/wjtregaskis/" title="Wade's stuff. Little bland, but contains a gem in the form of Rotated Windows.">Wade Tregaskis</a> and his Rotating Windows.</p>

<p>&copy; 2006 Ankur Kothari.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/the-ultimate-core-graphics-resource/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
