Saw the generated code for drawing inner shadow. Everything is pretty clear and understood except for the portion whereby the shadow is created with copysign.
I understand what copysign does but why and how is it actually being used in the code below.
The 0.1 value seem insignificant to the xOffset value.
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *shadow = [UIColor redColor];
CGSize shadowOffset = CGSizeMake(-2, -0);
CGFloat shadowBlurRadius = 2;
UIBezierPath *rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(50, 50, 50, 50)];
[[UIColor grayColor] setFill];
[rectanglePath fill];
CGRect rectangleBorderRect = CGRectInset([rectanglePath bounds], -shadowBlurRadius, -shadowBlurRadius);
rectangleBorderRect = CGRectOffset(rectangleBorderRect, -shadowOffset.width, -shadowOffset.height);
rectangleBorderRect = CGRectInset(CGRectUnion(rectangleBorderRect, [rectanglePath bounds]), -1, -1);
UIBezierPath *rectangleNegativePath = [UIBezierPath bezierPathWithRect: rectangleBorderRect];
[rectangleNegativePath appendPath: rectanglePath];
rectangleNegativePath.usesEvenOddFillRule = YES;
CGContextSaveGState(context);
{
CGFloat xOffset = shadowOffset.width + round(rectangleBorderRect.size.width);
CGFloat yOffset = shadowOffset.height;
CGContextSetShadowWithColor(context,
CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)),
shadowBlurRadius,
shadow.CGColor);
[rectanglePath addClip];
CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(rectangleBorderRect.size.width), 0);
[rectangleNegativePath applyTransform: transform];
[[UIColor grayColor] setFill];
[rectangleNegativePath fill];
}
CGContextRestoreGState(context);
Developer of PaintCode here.
Shadows offsets are always "rounded" to integral pixels. Unfortunately, there is some sort of precision/rounding issue in Core Graphics. For certain values of shadow offsets, the rounding somehow goes off and an incorrect offset is used (for example, 2 instead of 3).
By strategically adding or subtracting 0.1 from the shadow offset, we force it to always behave correctly.