-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Makes drawing more smoothly #14
base: main
Are you sure you want to change the base?
Conversation
waterzhang0423
commented
Dec 19, 2015
- calc draw steps per bezier dynamically
- use setNeedsDisplayInRect instead of setNeedsDisplay
1. calc draw steps per bezier dynamically 2. use setNeedsDisplayInRect instead of setNeedsDisplay
Add a demo pic
This seems good, but it looks like it's causing tests to fail. Also, you've made changes to the README that don't make sense. Can you pass the tests and revert the readme changes? |
This reverts commit e2042e0.
Sorry, I pushed a commit accidentally. I reverted all the changes except |
Hi @waterzhang0423, thanks for contributing to jot! I hope you've found it useful. Currently, the changes to The "min width bezier" section you added to Drawing a minimum-width bezier curve on top of the variable-width bezier curve shouldn't do anything to improve the smoothness, since most of the points on a variable-width curve will be wider than this overlaid curve. Removing that code leaves the shadow that you've added, which is also black, and conflicts with colored drawings like this- As you can see, there are some individual dots visible here and the drawing is not very smooth, which the shadow highlights. Using the original Unfortunately, I don't think these changes to I'm interested in the changes you made to |
Hi, @lauraskelton, thank you for reply such detail. I feel so sorry now, I haven't tested drawing with non-black. I fixed it. I forgot to call First, I run the 4 points can draw a bezier, but a shorter bezier path should draw less points, so I thought maybe use 300 points to draw each bezier can be changed. So I calculated each path length(sum distances between 4 points), the accuracy of result may not right in some curve cases. Calc draw steps per bezier will get this. Then, I tried to find a way to blur the path edge, I thought it would make bezier path smoother, so I set shadow for each path. Now it is like this. If set About the |
Fixed non-black drawing bug. //
// JotTouchBezier.m
// jot
//
// Created by Laura Skelton on 4/30/15.
//
//
#import "JotTouchBezier.h"
NSUInteger const kJotDrawStepsPerBezier = 300;
CGFloat const kJotBezierShadow = 0.65f;
static inline CGFloat pointLength(const CGPoint point1, const CGPoint point2){
return sqrt(pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2));
}
@implementation JotTouchBezier
+ (instancetype)withColor:(UIColor *)color
{
JotTouchBezier *touchBezier = [JotTouchBezier new];
touchBezier.strokeColor = color;
return touchBezier;
}
- (void)jotDrawBezier
{
if (self.constantWidth) {
UIBezierPath *bezierPath = [UIBezierPath new];
[bezierPath moveToPoint:self.startPoint];
[bezierPath addCurveToPoint:self.endPoint controlPoint1:self.controlPoint1 controlPoint2:self.controlPoint2];
bezierPath.lineWidth = self.startWidth;
bezierPath.lineCapStyle = kCGLineCapRound;
[self.strokeColor setStroke];
[bezierPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.f];
} else {
[self.strokeColor setFill];
CGFloat minWidth = self.startWidth;
CGFloat widthDelta = self.endWidth - self.startWidth;
CGFloat length = pointLength(self.startPoint, self.controlPoint1)
+ pointLength(self.controlPoint1, self.controlPoint2)
+ pointLength(self.controlPoint2, self.endPoint);
CGFloat drawSteps = MAX(MIN(length,kJotDrawStepsPerBezier),10);
CGContextRef context = UIGraphicsGetCurrentContext();
if (!context) {
return;
}
// Set shadow makes bezier path more smoothly
CGContextSetShadowWithColor(context, CGSizeMake(0, 0), kJotBezierShadow, self.strokeColor.CGColor);
for (NSUInteger i = 0; i < drawSteps; i++) {
CGFloat t = ((CGFloat)i) / (CGFloat)drawSteps;
CGFloat tt = t * t;
CGFloat ttt = tt * t;
CGFloat u = 1.f - t;
CGFloat uu = u * u;
CGFloat uuu = uu * u;
CGFloat x = uuu * self.startPoint.x;
x += 3 * uu * t * self.controlPoint1.x;
x += 3 * u * tt * self.controlPoint2.x;
x += ttt * self.endPoint.x;
CGFloat y = uuu * self.startPoint.y;
y += 3 * uu * t * self.controlPoint1.y;
y += 3 * u * tt * self.controlPoint2.y;
y += ttt * self.endPoint.y;
CGFloat pointWidth = self.startWidth + (ttt * widthDelta);
minWidth = MIN(pointWidth, minWidth);
[self.class jotDrawBezierPoint:CGPointMake(x, y) withWidth:pointWidth];
}
// Draw a min width bezier, in case of drawSteps is not enough
CGFloat span = 0.0f;
CGPoint startPoint = CGPointMake(self.startPoint.x, self.startPoint.y + span);
CGPoint controlPoint1 = CGPointMake(self.controlPoint1.x, self.controlPoint1.y + span);
CGPoint controlPoint2 = CGPointMake(self.controlPoint2.x, self.controlPoint2.y + span);
CGPoint endPoint = CGPointMake(self.endPoint.x, self.endPoint.y + span);
[self.strokeColor setStroke];
CGContextSetLineWidth(context, minWidth);
CGContextSetAllowsAntialiasing(context, true);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddCurveToPoint(context, controlPoint1.x, controlPoint1.y,
controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
CGContextStrokePath(context);
}
}
+ (void)jotDrawBezierPoint:(CGPoint)point withWidth:(CGFloat)width
{
CGContextRef context = UIGraphicsGetCurrentContext();
if (!context) {
return;
}
CGContextFillEllipseInRect(context, CGRectInset(CGRectMake(point.x, point.y, 0.f, 0.f), -width / 2.f, -width / 2.f));
}
@end
|