Вот рабочее решение.
Одна растровая маска с вертикальным градиентом используется как есть, так и отражается при рисовании двух цветовых градиентов.
Компоненты FourTimesRGB - это компоненты R, G, B, A четырех угловых цветов UL, UR, LL и LR, то есть ULR, ULG, ULB, ULA, URR и т. Д.
void DrawFourGradientRect(CGContextRef Cgc,
const CGRect * Rect,
const CGFloat FourTimesRGBAcomponents[16])
{
int w;
int h;
void *MaskData;
CGColorSpaceRef GrayCS;
CGColorSpaceRef CS;
CGContextRef BC; //Bitmap context
CGFloat GrayComp[4] = {1.0, 1.0, 0.0, 1.0}; //2 * Gray+Alpha
CGGradientRef Gradient;
CGImageRef Mask;
w = Rect->size.width;
h = Rect->size.height;
//Start filling with white
CGContextSetRGBFillColor(Cgc, 1, 1, 1, 1);
CGContextFillRect(Cgc, *Rect);
//Then create vertical gradient mask bitmap, white on top, black at bottom
MaskData = malloc(w * h);
if (!MaskData)
return;
GrayCS = CGColorSpaceCreateDeviceGray();
if (!GrayCS)
{
free(MaskData);
return;
}
BC = CGBitmapContextCreate(MaskData, w, h, 8, w, GrayCS, kCGImageAlphaNone);
if (!BC)
{
CGColorSpaceRelease(GrayCS);
free(MaskData);
return;
}
Gradient = CGGradientCreateWithColorComponents(GrayCS, GrayComp, NULL, 2);
if (!Gradient)
{
CGContextRelease(BC);
CGColorSpaceRelease(GrayCS);
free(MaskData);
return;
}
CGColorSpaceRelease(GrayCS);
CGContextDrawLinearGradient(BC, Gradient, CGPointZero, CGPointMake(0, h), 0);
CGGradientRelease(Gradient);
Mask = CGBitmapContextCreateImage(BC);
CGContextRelease(BC);
free(MaskData);
if (!Mask)
return;
//Now draw first horizontal color gradient from UL to UR
CS = CGColorSpaceCreateDeviceRGB();
if (!CS)
{
CGImageRelease(Mask);
return;
}
CGContextSaveGState(Cgc);
CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y);
CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);
Gradient = CGGradientCreateWithColorComponents(CS,
FourTimesRGBAcomponents, NULL, 2);
if (Gradient)
{
CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
CGGradientRelease(Gradient);
}
CGContextRestoreGState(Cgc);
//Finally draw second horizontal color gradient from LL to LR
CGContextSaveGState(Cgc);
CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y + Rect->size.height);
CGContextScaleCTM(Cgc, 1, -1); //Use vertical gradient mask upside-down
CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);
Gradient = CGGradientCreateWithColorComponents(CS,
FourTimesRGBAcomponents + 8, NULL, 2);
if (Gradient)
{
CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
CGGradientRelease(Gradient);
}
CGContextRestoreGState(Cgc);
CGImageRelease(Mask);
CGColorSpaceRelease(CS);
} /* DrawFourGradientRect */