void 
FlipContextIfNeeded(CGContextRef inContext, HIThemeOrientation inOrientation, HIRect const *inBounds)
{
	switch (inOrientation)
	{
		case kHIThemeOrientationNormal:
			return;
		case kHIThemeOrientationInverted:
		{
			float height = inBounds->origin.y + inBounds->origin.y + inBounds->size.height;
			CGContextTranslateCTM(inContext, 0.0, height);
			CGContextScaleCTM(inContext, 1.0, -1.0);
		}
	}
}


void
UnflipContextIfNeeded(CGContextRef inContext, HIThemeOrientation inOrientation, HIRect const *inBounds)
{
	switch (inOrientation)
	{
		case kHIThemeOrientationNormal:
			return;
		case kHIThemeOrientationInverted:
		{
			float height = inBounds->origin.y + inBounds->origin.y + inBounds->size.height;
			CGContextScaleCTM(inContext, 1.0, -1.0);
			CGContextTranslateCTM(inContext, 0.0, -height);
		}
	}
}


CGColorSpaceRef 
CGColorSpaceGetMainDisplay()
{
	// - This is based on Technical Q&A #1396
	//   http://developer.apple.com/qa/qa2004/qa1396.html

	static CGColorSpaceRef sDisplayColorSpace = NULL;
	if (!sDisplayColorSpace)
	{	
		// - Get the Systems Profile for the main display

		CMProfileRef sysprof = NULL;
		if (noErr == CMGetSystemProfile(&sysprof))
		{
			// - Create a colorspace with the systems profile

			sDisplayColorSpace = CGColorSpaceCreateWithPlatformColorSpace(sysprof);

			// - Close the profile

			CMCloseProfile(sysprof);
		}
	}

	return sDisplayColorSpace;
}


static void
MyDrawPattern(void *info, CGContextRef context)
{
	if (info && context)
	{
		CGImageRef image = (CGImageRef)info;
		CGRect rect = { CGPointZero, {1.0, 1.0} };
		CGContextDrawImage(context, rect, image);
	}
}


static void
MyReleasePattern(void *info)
{
	if (info) 
		CGImageRelease((CGImageRef)info);
}


static CGPatternCallbacks MyCGPatternCallbacks =
{
	0, // version
	MyDrawPattern,
	MyReleasePattern
};


static CGPatternRef
CreatePatternForImage(CGImageRef tiledImage, size_t *outImageHeight)
{
	if (!tiledImage) return NULL;

	size_t imageHeight = CGImageGetHeight(tiledImage);
	if (outImageHeight)
		*outImageHeight = imageHeight;

	CGRect patternBounds = { CGPointZero, {1.0, 1.0} };
	CGAffineTransform transform = CGAffineTransformMakeScale(CGImageGetWidth (tiledImage), imageHeight);

	CGPatternRef pattern = NULL;
	pattern = CGPatternCreate(tiledImage, 
							  patternBounds, 
							  transform, 
							  1.0, 
							  1.0, 
							  kCGPatternTilingConstantSpacingMinimalDistortion, 
							  true, 
							  &MyCGPatternCallbacks);
	if (!pattern) return NULL;

	// the callback will release tiledImage
	CGImageRetain(tiledImage);

	return pattern;
}


static OSStatus
DrawPattern(CGRect const *inBounds, CGPatternRef inPattern, size_t inTileHeight, CGContextRef inContext)
{
	if (!inBounds || !inPattern || !inContext)
		return paramErr;

	CGColorSpaceRef patternColorspace = CGColorSpaceCreatePattern(NULL);
	if (!patternColorspace)
		return notEnoughMemoryErr;

	int verticalPhase = inTileHeight ? ((int)inBounds->size.height % inTileHeight) : 0;
	CGSize phase = {0.0, verticalPhase};

	CGContextSetPatternPhase(inContext, phase);
	float const colorComponents[] = {1.0};
	CGContextSetFillColorSpace(inContext, patternColorspace);
	CGContextSetFillPattern(inContext, inPattern, colorComponents);
	CGContextFillRect(inContext, *inBounds);
	CGColorSpaceRelease(patternColorspace);

	return noErr;
}


OSStatus 
TileImage(HIRect const *inBounds, CGImageRef inImage, CGContextRef inContext, HIThemeOrientation inOrientation)
{
	OSStatus result = paramErr;

	size_t tileHeight;
	CGPatternRef pattern = CreatePatternForImage(inImage, &tileHeight);
	if (pattern)
	{
		CGColorSpaceRef displaySpace = CGColorSpaceGetMainDisplay();
		if (displaySpace)
		{
			CGContextSaveGState(inContext);
			FlipContextIfNeeded(inContext, inOrientation, inBounds);
			CGContextSetFillColorSpace(inContext, displaySpace);
			result = DrawPattern( (CGRect const *)inBounds, pattern, tileHeight, inContext);
			UnflipContextIfNeeded( inContext, inOrientation, inBounds );
			CGContextRestoreGState(inContext);
		}
		CGPatternRelease(pattern);
	}

	return result;
}