| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- //
- // SignatureViewM.m
- // HelloTriangle
- //
- // Created by Rui Zhang on 4/20/23.
- // Copyright © 2023 Apple. All rights reserved.
- //
- #import "SignatureViewM.h"
- #import "const.h"
- #import "RAUtils.h"
- //#import "AAPLRenderer.h"
- #define STROKE_WIDTH_SMOOTHING 0.5 // Low pass filter alpha
- #define VELOCITY_CLAMP_MIN 20
- #define VELOCITY_CLAMP_MAX 5000
- #define QUADRATIC_DISTANCE_TOLERANCE 3.0 // Minimum distance to make a curve
- #define MAXIMUM_VERTECES 100000
- static vector_float4 StrokeColor = { 0, 0, 0, 1 };
- static vector_float4 clearColor = { 1, 1, 1, 0 };
- //typedef struct
- //{
- //
- //} AAPLVertex;
- static const uint maxLength = MAXIMUM_VERTECES;
- static inline void addVertex(uint *Totallength,NSMutableArray *partlength, PPSSignaturePoint v,PPSSignaturePoint* dest) {
- if ((*Totallength) >= maxLength) {
- return;
- }
-
-
- dest[*Totallength]=v;
- //
- // GLvoid *data = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
- // memcpy(data + sizeof(PPSSignaturePoint) * (*length), &v, sizeof(PPSSignaturePoint));
- // glUnmapBufferOES(GL_ARRAY_BUFFER);
- //
-
- partlength[partlength.count-1]=@([partlength[partlength.count-1] intValue] +1);
-
-
-
-
-
- (*Totallength)++;
-
- #ifdef DEBUG
- NSLog(@"dest %p total %d part %ld ,partlength %@ vertex (%f,%f)(%f,%f,%f,%f)",dest,*Totallength,partlength.count-1, partlength[partlength.count-1],v.position[0],v.position[1],v.color[0],v.color[1],v.color[2],v.color[3]);
- #endif
-
- }
- static inline CGPoint QuadraticPointInCurve(CGPoint start, CGPoint end, CGPoint controlPoint, float percent) {
- double a = pow((1.0 - percent), 2.0);
- double b = 2.0 * percent * (1.0 - percent);
- double c = pow(percent, 2.0);
-
- return (CGPoint) {
- a * start.x + b * controlPoint.x + c * end.x,
- a * start.y + b * controlPoint.y + c * end.y
- };
- }
- static float generateRandom(float from, float to) { return random() % 10000 / 10000.0 * (to - from) + from; }
- static float clamp(float min, float max, float value) { return fmaxf(min, fminf(max, value)); }
- // Find perpendicular vector from two other vectors to compute triangle strip around line
- static vector_float2 perpendicular(PPSSignaturePoint p1, PPSSignaturePoint p2) {
-
- vector_float2 ret={0,0};
- // GLKVector3 ret;
- ret[0] = p2.position[1] - p1.position[1];
- ret[1] = -1 * (p2.position[0] - p1.position[0]);
-
- return ret;
- }
- static PPSSignaturePoint ViewPointToMTK(CGPoint viewPoint, CGSize view_size,CGSize drawable_size ,vector_float4 color) {
-
- vector_float2 inverseViewSize={1.0f / view_size.width, 1.0f / view_size.height}; // passed in a buffer
- float clipX = (2.0f * viewPoint.x * inverseViewSize.x) - 1.0f;
- float clipY = (2.0f * -viewPoint.y * inverseViewSize.y) + 1.0f;
-
-
- return (PPSSignaturePoint) {
- {
- clipX*drawable_size.width/2,
- clipY*drawable_size.height/2
- },
- {color[0],color[1],color[2],color[3]}
- };
-
-
-
-
- //
- // float4 clipPosition(clipX, clipY, 0.0f, 1.0f);
- }
- @interface SignatureViewM ()
- @property(nonatomic,assign)CGPoint mixPoint;
- @property(nonatomic,assign)CGPoint maxPoint;
- //@property (assign, nonatomic) NSMutableArray *drawable;
- @end
- @interface SignatureViewM () {
- // OpenGL state
- // EAGLContext *context;
- // GLKBaseEffect *effect;
-
- // GLuint vertexArray;
- // GLuint vertexBuffer;
- // GLuint dotsArray;
- // GLuint dotsBuffer;
- //
-
- // Array of verteces, with current length
- PPSSignaturePoint SignatureVertexData[maxLength];
- uint vertexTotal;
- NSMutableArray* vertexLength;
-
- PPSSignaturePoint SignatureDotsData[maxLength];
- uint dotsTotal;
- // NSMutableArray* dotsLength;
-
- // Width of line at current and previous vertex
- float penThickness;
- float previousThickness;
-
-
- // Previous points for quadratic bezier computations
- CGPoint previousPoint;
- CGPoint previousMidPoint;
- PPSSignaturePoint previousVertex;
- PPSSignaturePoint currentVelocity;
-
-
- }
- @end
- @implementation SignatureViewM
- SignatureRenderer *_renderer;
- - (void)commonInit {
- [self setLineWidth:5];
- self.framebufferOnly=false;
- vertexLength = [NSMutableArray new];
- [vertexLength addObject:@0];
- // dotsLength = [NSMutableArray new];
- //#define STROKE_WIDTH_MIN 0.004 // Stroke width determined by touch velocity
- //#define STROKE_WIDTH_MAX 0.010
- self.MaxLineWidth = 0.010*1000;
- self.MinLineWidth = 0.004*1000;
-
- self.device = MTLCreateSystemDefaultDevice();
-
-
- NSAssert(self.device, @"Metal is not supported on this device");
-
- _renderer = [[SignatureRenderer alloc] initWithMetalKitView:self];
-
- _renderer.parts =vertexLength;
- _renderer.SignatureVertexData = SignatureVertexData;
-
- NSAssert(_renderer, @"Renderer failed initialization");
- // Initialize our renderer with the view size
- [_renderer mtkView:self drawableSizeWillChange:self.drawableSize];
- self.delegate = _renderer;
-
- // context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- //
- // if (context) {
- // time(NULL);
- //
- // self.backgroundColor = [UIColor clearColor];
- // self.opaque = YES;
- //
- // self.context = context;
- // self.drawableDepthFormat = GLKViewDrawableDepthFormat24;
- // self.enableSetNeedsDisplay = YES;
- //
- // // Turn on antialiasing
- // self.drawableMultisample = GLKViewDrawableMultisample4X;
- //
- // [self setupGL];
- //
- // Capture touches
- UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
- pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1;
- pan.cancelsTouchesInView = YES;
- [self addGestureRecognizer:pan];
-
- // For dotting your i's
- UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
- tap.cancelsTouchesInView = YES;
- tap.numberOfTapsRequired = 1;
- [self addGestureRecognizer:tap];
- //
- // Erase with long press
- // UILongPressGestureRecognizer *longer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
- // longer.cancelsTouchesInView = YES;
- // [self addGestureRecognizer:longer];
- //
- // } else [NSException raise:@"NSOpenGLES2ContextException" format:@"Failed to create OpenGL ES2 context"];
- }
- - (id)initWithCoder:(NSCoder *)aDecoder
- {
- if (self = [super initWithCoder:aDecoder])
- {
- [self commonInit];
- _mixPoint =CGPointMake(self.bounds.size.width, self.bounds.size.height);
- _maxPoint =CGPointMake(0, 0);
-
- }
- return self;
- }
- - (instancetype)initWithFrame:(CGRect)frameRect device:(id<MTLDevice>)device
- {
- if(self=[super initWithFrame:frameRect device:device])
- {
- [self commonInit];
- _mixPoint =CGPointMake(self.bounds.size.width, self.bounds.size.height);
- _maxPoint =CGPointMake(0, 0);
-
-
- }
- return self;
- }
- - (void)setLineWidth:(CGFloat)width {
- self.MaxLineWidth = width;//400.0;
- self.MinLineWidth = width*0.4;//400.0*0.4;
- penThickness = (self.MaxLineWidth - self.MinLineWidth)/2.0;
- }
- //清除画布
- - (void)clear {
- [vertexLength removeAllObjects];
- [vertexLength addObject:@0];
-
- vertexTotal =0;
-
- // _renderer.SignatureVertexData = SignatureVertexData;
- // dotsLength = nil;
- self.isSigned = NO;
- _mixPoint =CGPointMake(self.bounds.size.width, self.bounds.size.height);
- _maxPoint =CGPointMake(0, 0);
- [self setNeedsDisplay];
- }
- - (UIImage *)signatureImage {
- return [self Signature2Image];
- }
- - (NSData *)signatureData {
- UIImage* signatureImage = [self Signature2Image];
- return UIImagePNGRepresentation(signatureImage);
- }
- - (UIImage*)Signature2Image
- {
- if (!self.isSigned)
- return nil;
-
- UIImage *screenshot = [self snapshot];
- if(screenshot==nil)
- {
- NSAssert(false, @"screenshot is null");
- }
- float x = _mixPoint.x - MAX_LINEWIDTH /2.0;
- float y = _mixPoint.y - MAX_LINEWIDTH / 2.0;
- if(x<0)
- x=0;
- if(y<0)
- y=0;
-
- float screen_scale = [[UIScreen mainScreen] scale];
-
- CGRect rect = CGRectMake(x*screenshot.scale*screen_scale, y*screenshot.scale*screen_scale, (_maxPoint.x-_mixPoint.x+MAX_LINEWIDTH)*screenshot.scale*screen_scale, (_maxPoint.y-_mixPoint.y+MAX_LINEWIDTH)*screenshot.scale*screen_scale);
-
- CGImageRef imageRef=screenshot.CGImage;
- CGImageRef imagePartRef=CGImageCreateWithImageInRect(imageRef,rect);
- UIImage*cropImage=[UIImage imageWithCGImage:imagePartRef];
- CGImageRelease(imagePartRef);;
- if(cropImage==nil)
- {
- NSAssert(false, @"Signature2Image: cropImage is nil");
- // int debug = 1;
- }
-
- return cropImage;
- }
- /** 按给定的方向旋转图片 */
- - (UIImage*)rotate:(UIImage*)source orient:(UIImageOrientation)orient
- {
- CGRect bnds = CGRectZero;
- UIImage* copy = nil;
- CGContextRef ctxt = nil;
- CGImageRef imag = source.CGImage;
- CGRect rect = CGRectZero;
- CGAffineTransform tran = CGAffineTransformIdentity;
-
- rect.size.width = CGImageGetWidth(imag);
- rect.size.height = CGImageGetHeight(imag);
-
- bnds = rect;
-
- switch (orient)
- {
- case UIImageOrientationUp:
- return source;
-
- case UIImageOrientationUpMirrored:
- tran = CGAffineTransformMakeTranslation(rect.size.width, 0.0);
- tran = CGAffineTransformScale(tran, -1.0, 1.0);
- break;
-
- case UIImageOrientationDown:
- tran = CGAffineTransformMakeTranslation(rect.size.width,
- rect.size.height);
- tran = CGAffineTransformRotate(tran, M_PI);
- break;
-
- case UIImageOrientationDownMirrored:
- tran = CGAffineTransformMakeTranslation(0.0, rect.size.height);
- tran = CGAffineTransformScale(tran, 1.0, -1.0);
- break;
-
- // case UIImageOrientationLeft:
- // bnds = swapWidthAndHeight(bnds);
- // tran = CGAffineTransformMakeTranslation(0.0, rect.size.width);
- // tran = CGAffineTransformRotate(tran, 3.0 * M_PI / 2.0);
- // break;
- //
- // case UIImageOrientationLeftMirrored:
- // bnds = swapWidthAndHeight(bnds);
- // tran = CGAffineTransformMakeTranslation(rect.size.height,
- // rect.size.width);
- // tran = CGAffineTransformScale(tran, -1.0, 1.0);
- // tran = CGAffineTransformRotate(tran, 3.0 * M_PI / 2.0);
- // break;
- //
- // case UIImageOrientationRight:
- // bnds = swapWidthAndHeight(bnds);
- // tran = CGAffineTransformMakeTranslation(rect.size.height, 0.0);
- // tran = CGAffineTransformRotate(tran, M_PI / 2.0);
- // break;
- //
- // case UIImageOrientationRightMirrored:
- // bnds = swapWidthAndHeight(bnds);
- // tran = CGAffineTransformMakeScale(-1.0, 1.0);
- // tran = CGAffineTransformRotate(tran, M_PI / 2.0);
- // break;
-
- default:
- return source;
- }
-
- UIGraphicsBeginImageContext(bnds.size);
- ctxt = UIGraphicsGetCurrentContext();
-
- switch (orient)
- {
- case UIImageOrientationLeft:
- case UIImageOrientationLeftMirrored:
- case UIImageOrientationRight:
- case UIImageOrientationRightMirrored:
- CGContextScaleCTM(ctxt, -1.0, 1.0);
- CGContextTranslateCTM(ctxt, -rect.size.height, 0.0);
- break;
-
- default:
- CGContextScaleCTM(ctxt, 1.0, -1.0);
- CGContextTranslateCTM(ctxt, 0.0, -rect.size.height);
- break;
- }
-
- CGContextConcatCTM(ctxt, tran);
- CGContextDrawImage(UIGraphicsGetCurrentContext(), rect, imag);
-
- copy = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
-
- return copy;
- }
- -(UIImage*) snapshot
- {
-
- CIContext * context = [CIContext contextWithMTLDevice:self.device];
- CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:self.currentDrawable.texture options:@{kCIImageColorSpace:(__bridge_transfer id)CGColorSpaceCreateDeviceRGB()}];
- CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, [UIScreen mainScreen].nativeBounds.size.width, [UIScreen mainScreen].nativeBounds.size.height)];
- UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:1.0 orientation:UIImageOrientationUp];
-
- resultImg = [self rotate:resultImg orient: UIImageOrientationDownMirrored];
-
- //
- // UIImageOrientationUp, // default orientation
- // UIImageOrientationDown, // 180 deg rotation
- // UIImageOrientationLeft, // 90 deg CCW
- // UIImageOrientationRight, // 90 deg CW
- // UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip
- // UIImageOrientationDownMirrored, // horizontal flip
- // UIImageOrientationLeftMirrored, // vertical flip
- // UIImageOrientationRightMirrored, // vertical flip
-
-
- CGImageRelease(cgImg);
- return resultImg;
- // id<MTLTexture> lastDrawableDisplayed = [self.currentDrawable texture];
- //
- // int width = (int)[lastDrawableDisplayed width];
- // int height = (int)[lastDrawableDisplayed height];
- // int rowBytes = width * 4;
- // int selfturesize = width * height * 4;
- //
- // void *p = malloc(selfturesize);
- //
- //
- //
- // [lastDrawableDisplayed getBytes:p bytesPerRow:rowBytes fromRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0];
- //
- // CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- // CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst;
- //
- // CGDataProviderRef provider = CGDataProviderCreateWithData(nil, p, selfturesize, nil);
- // CGImageRef cgImageRef = CGImageCreate(width, height, 8, 32, rowBytes, colorSpace, bitmapInfo, provider, nil, true, (CGColorRenderingIntent)kCGRenderingIntentDefault);
- //
- // UIImage *getImage = [UIImage imageWithCGImage:cgImageRef];
- // CGImageRelease(cgImageRef);
- //
- // CGDataProviderRelease(provider);
- // CGColorSpaceRelease(colorSpace);
- // free(p);
- // return getImage;
- //
- // NSData *pngData = UIImagePNGRepresentation(getImage);
- // UIImage *pngImage = [UIImage imageWithData:pngData];
- }
- - (void)updateStrokeColor {
-
- CGFloat red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0, white = 0.0;
- if ( self.strokeColor && [self.strokeColor getRed:&red green:&green blue:&blue alpha:&alpha]) {
- StrokeColor[0]=red;
- StrokeColor[1]=green;
- StrokeColor[2]=blue;
- StrokeColor[3]=alpha;
- } else if (self.strokeColor && [self.strokeColor getWhite:&white alpha:&alpha]) {
-
- StrokeColor[0]=white;
- StrokeColor[1]=white;
- StrokeColor[2]=white;
- StrokeColor[3]=alpha;
-
-
- } else
- {
- StrokeColor[0]=0;
- StrokeColor[1]=0;
- StrokeColor[2]=0;
- StrokeColor[3]=1;
- }
- // StrokeColor
- }
- - (void)setBackgroundColor:(UIColor *)backgroundColor {
- [super setBackgroundColor:backgroundColor];
-
- CGFloat red, green, blue, alpha, white;
- if ([backgroundColor getRed:&red green:&green blue:&blue alpha:&alpha]) {
- clearColor[0] = red;
- clearColor[1] = green;
- clearColor[2] = blue;
- } else if ([backgroundColor getWhite:&white alpha:&alpha]) {
- clearColor[0] = white;
- clearColor[1] = white;
- clearColor[2] = white;
- }
- }
- - (void)setStrokeColor:(UIColor *)strokeColor {
- _strokeColor = strokeColor;
- [self updateStrokeColor];
- }
- - (void)updateRectWithPoint:(CGPoint)p
- {
- if (p.x<_mixPoint.x) {
- _mixPoint.x =p.x;
- }
- if (p.y<_mixPoint.y) {
- _mixPoint.y =p.y;
- }
- if (p.x>_maxPoint.x) {
- _maxPoint.x =p.x;
- }
- if (p.y>_maxPoint.y) {
- _maxPoint.y =p.y;
- }
- }
- /*
- // Only override drawRect: if you perform custom drawing.
- // An empty implementation adversely affects performance during animation.
- - (void)drawRect:(CGRect)rect {
- // Drawing code
- }
- */
- #pragma mark - Gesture Recognizers
- - (void)tap:(UITapGestureRecognizer *)t {
- DebugLog(@"on tap");
- CGPoint l = [t locationInView:self];
-
- // l=CGPointMake(self.bounds.size.width/2, 0);
- [self updateRectWithPoint:l];
- if (t.state == UIGestureRecognizerStateRecognized) {
-
- self.isSigned = YES;
- DebugLog(@"UIGestureRecognizerStateRecognized");
-
-
- // glBindBuffer(GL_ARRAY_BUFFER, dotsBuffer);
- //
- // [dotsLength addObject:@0];
-
-
- PPSSignaturePoint touchPoint = ViewPointToMTK(l, self.bounds.size, self.drawableSize, StrokeColor);
- addVertex(&vertexTotal,vertexLength, touchPoint,SignatureVertexData);
- //
- PPSSignaturePoint centerPoint = touchPoint;
-
- centerPoint.color =StrokeColor;
- addVertex(&vertexTotal,vertexLength, centerPoint,SignatureVertexData);
- //
- static int segments = 20;
- vector_float2 radius = (vector_float2){
- clamp(1, 8, penThickness * generateRandom(2, 12)),
- clamp(1, 8, penThickness * generateRandom(2, 12))
- };
- vector_float2 velocityRadius = radius;
- float angle = 0;
- for (int i = 0; i <= segments; i++) {
- PPSSignaturePoint p = centerPoint;
- p.position.x += velocityRadius.x * cosf(angle);
- p.position.y += velocityRadius.y * sinf(angle);
- addVertex(&vertexTotal,vertexLength, p,SignatureVertexData);
- addVertex(&vertexTotal,vertexLength, centerPoint,SignatureVertexData);
- angle += M_PI * 2.0 / segments;
- }
- addVertex(&vertexTotal,vertexLength, touchPoint,SignatureVertexData);
- //
- // glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- [self setNeedsDisplay];
- }
- //- (void)longPress:(UILongPressGestureRecognizer *)lp {
- // //注释regturn,可以打开长按清除
- // return;
- //
- //// [self signatureImage];
- // [self clear];
- //}
- - (void)pan:(UIPanGestureRecognizer *)p {
-
- // glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
- //
- CGPoint v = [p velocityInView:self];
- CGPoint l = [p locationInView:self];
- [self updateRectWithPoint:l];
-
- currentVelocity = ViewPointToMTK(v, self.bounds.size, self.drawableSize,StrokeColor);
- float distance = 0.;
- if (previousPoint.x > 0) {
- distance = sqrtf((l.x - previousPoint.x) * (l.x - previousPoint.x) + (l.y - previousPoint.y) * (l.y - previousPoint.y));
- }
-
- float velocityMagnitude = sqrtf(v.x*v.x + v.y*v.y);
- float clampedVelocityMagnitude = clamp(VELOCITY_CLAMP_MIN, VELOCITY_CLAMP_MAX, velocityMagnitude);
- float normalizedVelocity = (clampedVelocityMagnitude - VELOCITY_CLAMP_MIN) / (VELOCITY_CLAMP_MAX - VELOCITY_CLAMP_MIN);
-
- float lowPassFilterAlpha = STROKE_WIDTH_SMOOTHING;
- float newThickness = (self.MaxLineWidth - self.MinLineWidth) * (1 - normalizedVelocity) + self.MinLineWidth;
- penThickness = penThickness * lowPassFilterAlpha + newThickness * (1 - lowPassFilterAlpha);
-
- if ([p state] == UIGestureRecognizerStateBegan) {
-
- previousPoint = l;
- previousMidPoint = l;
-
- PPSSignaturePoint startPoint = ViewPointToMTK(l, self.bounds.size, self.drawableSize,StrokeColor);
- previousVertex = startPoint;
- previousThickness = penThickness;
-
- addVertex(&vertexTotal,vertexLength, startPoint,SignatureVertexData);
- addVertex(&vertexTotal,vertexLength, previousVertex,SignatureVertexData);
-
- self.isSigned = YES;
-
- } else if ([p state] == UIGestureRecognizerStateChanged) {
-
- CGPoint mid = CGPointMake((l.x + previousPoint.x) / 2.0, (l.y + previousPoint.y) / 2.0);
-
- if (distance > QUADRATIC_DISTANCE_TOLERANCE) {
- // Plot quadratic bezier instead of line
- unsigned int i;
-
- int segments = (int) distance / 1.5;
-
- float startPenThickness = previousThickness;
- float endPenThickness = penThickness;
- previousThickness = penThickness;
-
- for (i = 0; i < segments; i++)
- {
- penThickness = startPenThickness + ((endPenThickness - startPenThickness) / segments) * i;
-
- CGPoint quadPoint = QuadraticPointInCurve(previousMidPoint, mid, previousPoint, (float)i / (float)(segments));
-
- PPSSignaturePoint v = ViewPointToMTK(quadPoint, self.bounds.size,self.drawableSize, StrokeColor);
- [self addTriangleStripPointsForPrevious:previousVertex next:v];
-
- previousVertex = v;
- }
- } else if (distance > 1.0) {
-
- PPSSignaturePoint v = ViewPointToMTK(l, self.bounds.size,self.drawableSize, StrokeColor);
- [self addTriangleStripPointsForPrevious:previousVertex next:v];
-
- previousVertex = v;
- previousThickness = penThickness;
- }
-
- previousPoint = l;
- previousMidPoint = mid;
-
- } else if (p.state == UIGestureRecognizerStateEnded | p.state == UIGestureRecognizerStateCancelled) {
-
- PPSSignaturePoint v = ViewPointToMTK(l, self.bounds.size, self.drawableSize,StrokeColor);
- addVertex(&vertexTotal,vertexLength, v,SignatureVertexData);
-
- previousVertex = v;
- addVertex(&vertexTotal,vertexLength, previousVertex,SignatureVertexData);
- }
-
- [self setNeedsDisplay];
- }
- - (void)addTriangleStripPointsForPrevious:(PPSSignaturePoint)previous next:(PPSSignaturePoint)next {
- float toTravel = penThickness / 2.0;
-
- for (int i = 0; i < 2; i++) {
- vector_float2 p = perpendicular(previous, next);
- vector_float2 p1 = next.position;
- vector_float2 ref = p1+p;
-
- float distance = simd_distance(p1,ref);
- float difX = p1.x - ref.x;
- float difY = p1.y - ref.y;
- float ratio = -1.0 * (toTravel / distance);
-
- difX = difX * ratio;
- difY = difY * ratio;
-
- PPSSignaturePoint stripPoint = {
- { p1.x + difX, p1.y + difY},
- StrokeColor
- };
- addVertex(&vertexTotal,vertexLength, stripPoint,SignatureVertexData);
-
- toTravel *= -1;
- }
- }
- @end
|