static CGShadingRef CGShadingRefForRadialGradient(const SVGPaintServerRadialGradient* server) { CGPoint center = CGPoint(server->gradientCenter()); CGPoint focus = CGPoint(server->gradientFocal()); double radius = server->gradientRadius(); double fdx = focus.x - center.x; double fdy = focus.y - center.y; // Spec: If (fx, fy) lies outside the circle defined by (cx, cy) and r, set (fx, fy) // to the point of intersection of the line through (fx, fy) and the circle. if (sqrtf(fdx * fdx + fdy * fdy) > radius) { double angle = atan2(focus.y * 100.0, focus.x * 100.0); focus.x = cos(angle) * radius; focus.y = sin(angle) * radius; } CGFunctionCallbacks callbacks = {0, cgGradientCallback, NULL}; CGFloat domainLimits[2] = {0, 1}; CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1}; CGFunctionRef shadingFunction = CGFunctionCreate((void *)server, 1, domainLimits, 4, rangeLimits, &callbacks); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGShadingRef shading = CGShadingCreateRadial(colorSpace, focus, 0, center, radius, shadingFunction, true, true); CGColorSpaceRelease(colorSpace); CGFunctionRelease(shadingFunction); return shading; }
void TIPGradientSetBlendingMode( TIPMutableGradientRef aGradient, TIPGradientBlendingMode blendingMode ) { aGradient->blendingMode = blendingMode; void *evaluationFunction = NULL; switch( aGradient->blendingMode ) { case TIPLinearBlendingMode: evaluationFunction = &TIPGradientLinearEvaluation; break; case TIPChromaticBlendingMode: evaluationFunction = &TIPGradientChromaticEvaluation; break; case TIPInverseChromaticBlendingMode: evaluationFunction = &TIPGradientInverseChromaticEvaluation; break; default: evaluationFunction = &TIPGradientLinearEvaluation; break; } if( aGradient->gradientFunction != NULL ) CGFunctionRelease(aGradient->gradientFunction); CGFunctionCallbacks evaluationCallbackInfo = {0, evaluationFunction, NULL}; static const CGFloat input_value_range[2] = {0.0f, 1.0f}; // range for the evaluator input static const CGFloat output_value_ranges[8] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f}; // ranges for the evaluator output aGradient->gradientFunction = CGFunctionCreate(&(aGradient->elementList), 1, input_value_range, 4, output_value_ranges, &evaluationCallbackInfo); }
static CGShadingRef CGShadingRefForLinearGradient(const SVGPaintServerLinearGradient* server) { CGPoint start = CGPoint(server->gradientStart()); CGPoint end = CGPoint(server->gradientEnd()); CGFunctionCallbacks callbacks = {0, cgGradientCallback, NULL}; CGFloat domainLimits[2] = {0, 1}; CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1}; CGFunctionRef shadingFunction = CGFunctionCreate((void *)server, 1, domainLimits, 4, rangeLimits, &callbacks); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGShadingRef shading = CGShadingCreateAxial(colorSpace, start, end, shadingFunction, true, true); CGColorSpaceRelease(colorSpace); CGFunctionRelease(shadingFunction); return shading; }
CGShadingRef CanvasGradient::platformShading() { if (m_shading) return m_shading; const CGFloat intervalRanges[2] = { 0, 1 }; const CGFloat colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 }; const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, 0 }; CGFunctionRef colorFunction = CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); if (m_radial) m_shading = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction, true, true); else m_shading = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction, true, true); CGColorSpaceRelease(colorSpace); CGFunctionRelease(colorFunction); return m_shading; }