From fce2dc194e5fbfdeb39e57b3d036b6cebc84cc42 Mon Sep 17 00:00:00 2001 From: m1ga Date: Wed, 11 Mar 2026 21:27:41 +0100 Subject: [PATCH 1/3] Update iOS library --- ios/Classes/TiPaintModuleAssets.m | 15 +- ios/Classes/TiPaintPaintView.m | 259 ++++++---- ios/Classes/TiPaintPaintViewProxy.m | 89 +++- ios/Classes/WetPaintView.h | 40 +- ios/Classes/WetPaintView.m | 528 +++++++++++++++++---- ios/manifest | 14 +- ios/paint.xcodeproj/project.pbxproj | 74 ++- ios/timodule.xml | 12 + ios/titanium.xcconfig | 15 +- windows/CMakeLists.txt | 121 ----- windows/cmake/FindHAL.cmake | 95 ---- windows/cmake/FindJavascriptCore.cmake | 40 -- windows/cmake/FindLayoutEngine.cmake | 85 ---- windows/cmake/FindTitaniumKit.cmake | 104 ---- windows/cmake/FindTitaniumWindows_UI.cmake | 42 -- windows/cmake/TiPaint_Config.cmake | 11 - windows/documentation/changelog.md | 3 - windows/documentation/index.md | 30 -- windows/documentation/paintView.md | 33 -- windows/example/app.js | 55 --- windows/include/TiPaint.hpp | 40 -- windows/include/TiPaintView.hpp | 76 --- windows/manifest | 15 - windows/src/TiPaint.cpp | 36 -- windows/src/TiPaintView.cpp | 199 -------- windows/test/CMakeLists.txt | 7 - windows/timodule.xml | 5 - 27 files changed, 813 insertions(+), 1230 deletions(-) create mode 100644 ios/timodule.xml delete mode 100644 windows/CMakeLists.txt delete mode 100644 windows/cmake/FindHAL.cmake delete mode 100644 windows/cmake/FindJavascriptCore.cmake delete mode 100644 windows/cmake/FindLayoutEngine.cmake delete mode 100644 windows/cmake/FindTitaniumKit.cmake delete mode 100644 windows/cmake/FindTitaniumWindows_UI.cmake delete mode 100644 windows/cmake/TiPaint_Config.cmake delete mode 100644 windows/documentation/changelog.md delete mode 100644 windows/documentation/index.md delete mode 100644 windows/documentation/paintView.md delete mode 100644 windows/example/app.js delete mode 100644 windows/include/TiPaint.hpp delete mode 100644 windows/include/TiPaintView.hpp delete mode 100644 windows/manifest delete mode 100644 windows/src/TiPaint.cpp delete mode 100644 windows/src/TiPaintView.cpp delete mode 100644 windows/test/CMakeLists.txt delete mode 100644 windows/timodule.xml diff --git a/ios/Classes/TiPaintModuleAssets.m b/ios/Classes/TiPaintModuleAssets.m index f4d9b74..1eff14a 100644 --- a/ios/Classes/TiPaintModuleAssets.m +++ b/ios/Classes/TiPaintModuleAssets.m @@ -3,13 +3,22 @@ */ #import "TiPaintModuleAssets.h" -extern NSData * dataWithHexString (NSString * hexString); +extern NSData* filterDataInRange(NSData* thedata, NSRange range); @implementation TiPaintModuleAssets -- (NSData*) moduleAsset +- (NSData *)moduleAsset { - return nil; + + + return nil; +} + +- (NSData *)resolveModuleAsset:(NSString *)path +{ + + + return nil; } @end diff --git a/ios/Classes/TiPaintPaintView.m b/ios/Classes/TiPaintPaintView.m index 3f2125a..73e267d 100644 --- a/ios/Classes/TiPaintPaintView.m +++ b/ios/Classes/TiPaintPaintView.m @@ -5,145 +5,198 @@ */ #import "TiPaintPaintView.h" +#import "TiBlob.h" #import "TiUtils.h" @implementation TiPaintPaintView -- (id)init -{ - if ((self = [super init])) - { - self.multipleTouchEnabled = YES; - wetPaintView = [[WetPaintView alloc] initWithFrame:self.bounds]; - wetPaintView.delegate = self; - [self addSubview:wetPaintView]; - [self bringSubviewToFront:wetPaintView]; - } - return self; -} - --(BOOL)proxyHasTapListener -{ - // The TiUIView only sets multipleTouchEnabled to YES if we have a tap listener. - // So... let's make it think that we do! (Note that we don't actually need one.) - return YES; -} - -- (void)dealloc -{ - [wetPaintView removeFromSuperview]; - RELEASE_TO_NIL(wetPaintView); - RELEASE_TO_NIL(drawImage); - - [super dealloc]; -} - -- (void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds -{ - [super frameSizeChanged:frame bounds:bounds]; - [wetPaintView setFrame:bounds]; - if (drawImage != nil) { - [drawImage setFrame:bounds]; - } - - // MOD-348: Ensure that we get a solid box in which to draw. Otherwise, we'll end - // up with blurry lines and visual defects. - drawBox = CGRectMake(bounds.origin.x, bounds.origin.y, - ceilf(bounds.size.width), ceilf(bounds.size.height)); +- (id)init { + if ((self = [super init])) { + self.multipleTouchEnabled = YES; + wetPaintView = [[WetPaintView alloc] initWithFrame:self.bounds]; + wetPaintView.delegate = self; + [self addSubview:wetPaintView]; + [self bringSubviewToFront:wetPaintView]; + } + return self; +} + +- (BOOL)proxyHasTapListener { + // The TiUIView only sets multipleTouchEnabled to YES if we have a tap + // listener. So... let's make it think that we do! (Note that we don't + // actually need one.) + return YES; +} + +- (void)dealloc { + [wetPaintView removeFromSuperview]; + RELEASE_TO_NIL(wetPaintView); + RELEASE_TO_NIL(drawImage); + + [super dealloc]; +} + +- (void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds { + [super frameSizeChanged:frame bounds:bounds]; + [wetPaintView setFrame:bounds]; + if (drawImage != nil) { + [drawImage setFrame:bounds]; + } + + // MOD-348: Ensure that we get a solid box in which to draw. Otherwise, we'll + // end up with blurry lines and visual defects. + drawBox = CGRectMake(bounds.origin.x, bounds.origin.y, + ceilf(bounds.size.width), ceilf(bounds.size.height)); } #pragma mark Utility -- (UIImageView*)imageView -{ - if (drawImage == nil) { - drawImage = [[UIImageView alloc] initWithImage:nil]; - drawImage.frame = [self bounds]; - [self addSubview:drawImage]; - [self bringSubviewToFront:wetPaintView]; - } - return drawImage; +- (UIImageView *)imageView { + if (drawImage == nil) { + drawImage = [[UIImageView alloc] initWithImage:nil]; + drawImage.frame = [self bounds]; + [self addSubview:drawImage]; + [self bringSubviewToFront:wetPaintView]; + } + return drawImage; } #pragma mark Wet Paint View Delegate --(void)readyToSavePaint -{ - UIGraphicsBeginImageContextWithOptions(drawBox.size, NO, 0.0); - CGContextRef context = UIGraphicsGetCurrentContext(); - [[self imageView].image drawInRect:CGRectMake(0, 0, drawBox.size.width, drawBox.size.height)]; - [wetPaintView drawInContext:context andApplyErase:YES]; - [self imageView].image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); +- (void)readyToSavePaint { + // This method now bakes all current strokes into the background image + // Called only when we actually need a final image (toBlob, setImage, clear, + // etc.) + UIGraphicsBeginImageContextWithOptions(drawBox.size, NO, 0.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + [[self imageView].image + drawInRect:CGRectMake(0, 0, drawBox.size.width, drawBox.size.height)]; + [wetPaintView drawInContext:context andApplyErase:YES]; + [self imageView].image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); } #pragma mark Public APIs -- (void)setEraseMode_:(id)value -{ - wetPaintView.erase = [TiUtils boolValue:value]; +- (void)setEraseMode_:(id)value { + wetPaintView.erase = [TiUtils boolValue:value]; +} + +- (void)setStrokeWidth_:(id)width { + wetPaintView.strokeWidth = [TiUtils floatValue:width]; +} + +- (void)setStrokeColor_:(id)value { + CGColorRelease(wetPaintView.strokeColor); + TiColor *color = [TiUtils colorValue:value]; + wetPaintView.strokeColor = [color _color].CGColor; + CGColorRetain(wetPaintView.strokeColor); +} + +- (void)setStrokeAlpha_:(id)alpha { + wetPaintView.strokeAlpha = [TiUtils floatValue:alpha] / 255.0; +} + +- (void)setImage_:(id)value { + ENSURE_UI_THREAD(setImage_, value); + + // Bake current strokes before setting new image + [wetPaintView bakeStrokesToDelegate]; + + RELEASE_TO_NIL(drawImage); + UIImage *image = [TiUtils image:value proxy:self.proxy] ?: nil; + + if (image != nil) { + drawImage = [[UIImageView alloc] initWithImage:image]; + drawImage.frame = [self bounds]; + [self addSubview:drawImage]; + [self bringSubviewToFront:wetPaintView]; + UIView *view = [self imageView]; + [drawImage.image drawInRect:CGRectMake(0, 0, view.frame.size.width, + view.frame.size.height)]; + } +} + +- (void)clear:(id)args { + if (drawImage != nil) { + drawImage.image = nil; + } + [wetPaintView clear]; +} + +- (void)undo:(id)args { + [wetPaintView undo]; +} + +- (void)redo:(id)args { + [wetPaintView redo]; +} + +- (TiBlob *)toBlob:(id)args { + // Force baking of all strokes before creating blob + [wetPaintView bakeStrokesToDelegate]; + + if ([self imageView].image != nil) { + return [TiBlob blobFromImage:[self imageView].image]; + } + return nil; } -- (void)setStrokeWidth_:(id)width -{ - wetPaintView.strokeWidth = [TiUtils floatValue:width]; +#pragma mark Playback Wrapper Methods + +- (void)playbackDrawing:(id)args { + NSNumber *duration = [args count] > 0 ? [args objectAtIndex:0] : @(5.0); + [wetPaintView playbackDrawing:[duration doubleValue]]; } -- (void)setStrokeColor_:(id)value -{ - CGColorRelease(wetPaintView.strokeColor); - TiColor *color = [TiUtils colorValue:value]; - wetPaintView.strokeColor = [color _color].CGColor; - CGColorRetain(wetPaintView.strokeColor); +- (void)pausePlayback:(id)args { + [wetPaintView pausePlayback]; } -- (void)setStrokeAlpha_:(id)alpha -{ - wetPaintView.strokeAlpha = [TiUtils floatValue:alpha] / 255.0; +- (void)resumePlayback:(id)args { + [wetPaintView resumePlayback]; } -- (void)setImage_:(id)value -{ - ENSURE_UI_THREAD(setImage_, value); - RELEASE_TO_NIL(drawImage); - UIImage* image = [TiUtils image:value proxy:self.proxy] ?: nil; - - if (image != nil) { - drawImage = [[UIImageView alloc] initWithImage:image]; - drawImage.frame = [self bounds]; - [self addSubview:drawImage]; - [self bringSubviewToFront:wetPaintView]; - UIView *view = [self imageView]; - [drawImage.image drawInRect:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)]; - } +- (void)stopPlayback:(id)args { + [wetPaintView stopPlayback]; +} + +- (void)setPlaybackSpeed:(id)args { + NSNumber *speed = (NSNumber *)args; + [wetPaintView setPlaybackSpeed:[speed floatValue]]; +} + +- (CGFloat)getPlaybackProgress { + return [wetPaintView getPlaybackProgress]; +} + +#pragma mark Save/Load Methods + +- (NSArray *)getStrokesData { + return [wetPaintView getStrokesData]; } -- (void)clear:(id)args -{ - if (drawImage != nil) { - drawImage.image = nil; - } +- (void)loadStrokes:(id)args { + NSArray *strokesArray = [args count] > 0 ? [args objectAtIndex:0] : @[]; + [wetPaintView loadStrokes:strokesArray]; } #pragma mark Events --(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ - [self processTouchesEnded:touches withEvent:event]; +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self processTouchesEnded:touches withEvent:event]; } -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self processTouchesBegan:touches withEvent:event]; +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self processTouchesBegan:touches withEvent:event]; } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self processTouchesMoved:touches withEvent:event]; +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self processTouchesMoved:touches withEvent:event]; } -- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self processTouchesCancelled:touches withEvent:event]; +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [self processTouchesCancelled:touches withEvent:event]; } @end diff --git a/ios/Classes/TiPaintPaintViewProxy.m b/ios/Classes/TiPaintPaintViewProxy.m index 5fcb7b8..24d9d54 100644 --- a/ios/Classes/TiPaintPaintViewProxy.m +++ b/ios/Classes/TiPaintPaintViewProxy.m @@ -5,14 +5,97 @@ */ #import "TiPaintPaintViewProxy.h" +#import "TiPaintPaintView.h" #import "TiUtils.h" @implementation TiPaintPaintViewProxy +- (void)clear:(id)args { + [[self view] performSelectorOnMainThread:@selector(clear:) + withObject:args + waitUntilDone:NO]; +} + +- (void)undo:(id)args { + [[self view] performSelectorOnMainThread:@selector(undo:) + withObject:args + waitUntilDone:NO]; +} + +- (void)redo:(id)args { + [[self view] performSelectorOnMainThread:@selector(redo:) + withObject:args + waitUntilDone:NO]; +} + +- (TiBlob *)toBlob:(id)args { + __block TiBlob *result = nil; + TiThreadPerformOnMainThread( + ^{ + result = [[self view] toBlob:args]; + }, + YES); + return result; +} + +// Playback methods +- (void)playbackDrawing:(id)args { + [[self view] performSelectorOnMainThread:@selector(playbackDrawing:) + withObject:args + waitUntilDone:NO]; +} + +- (void)pausePlayback:(id)args { + [[self view] performSelectorOnMainThread:@selector(pausePlayback:) + withObject:args + waitUntilDone:NO]; +} + +- (void)resumePlayback:(id)args { + [[self view] performSelectorOnMainThread:@selector(resumePlayback:) + withObject:args + waitUntilDone:NO]; +} + +- (void)stopPlayback:(id)args { + [[self view] performSelectorOnMainThread:@selector(stopPlayback:) + withObject:args + waitUntilDone:NO]; +} + +- (void)setPlaybackSpeed:(id)args { + [[self view] performSelectorOnMainThread:@selector(setPlaybackSpeed:) + withObject:args + waitUntilDone:NO]; +} + +- (NSNumber *)getPlaybackProgress:(id)args { + __block CGFloat result = 0.0; + TiThreadPerformOnMainThread( + ^{ + TiPaintPaintView *paintView = (TiPaintPaintView *)[self view]; + result = [paintView getPlaybackProgress]; + }, + YES); + return [NSNumber numberWithFloat:result]; +} + +// Save/Load methods +- (NSArray *)getStrokesData:(id)args { + __block NSArray *result = nil; + TiThreadPerformOnMainThread( + ^{ + TiPaintPaintView *paintView = (TiPaintPaintView *)[self view]; + result = [paintView getStrokesData]; + }, + YES); + return result; +} --(void)clear:(id)args -{ - [[self view] performSelectorOnMainThread:@selector(clear:) withObject:args waitUntilDone:NO]; +- (void)loadStrokes:(id)args { + [[self view] performSelectorOnMainThread:@selector(loadStrokes:) + withObject:args + waitUntilDone:NO]; } @end diff --git a/ios/Classes/WetPaintView.h b/ios/Classes/WetPaintView.h index e33e4c6..b175ffb 100644 --- a/ios/Classes/WetPaintView.h +++ b/ios/Classes/WetPaintView.h @@ -1,33 +1,59 @@ /** * WetPaintView.h * paint - * + * * Created by Dawson Toth on 4/20/12. * Copyright (c) 2012 Toth Solutions, LLC. All rights reserved. - * + * * Ti.Paint Module * Copyright (c) 2010-2013 by Appcelerator, Inc. All Rights Reserved. * Please see the LICENSE included with this distribution for details. */ -#import #import "TiUtils.h" +#import @protocol WetPaintViewDelegate @optional --(void)readyToSavePaint; +- (void)readyToSavePaint; @end @interface WetPaintView : UIView { - CFMutableDictionaryRef _touchLines; + CFMutableDictionaryRef _touchLines; + NSMutableArray *_completedStrokes; + NSMutableArray *_undoStrokes; + + // Playback state + NSTimer *_playbackTimer; + NSMutableArray *_playbackStrokes; + NSInteger _currentPlaybackIndex; + BOOL _isPlayingBack; + BOOL _isPaused; + NSTimeInterval _playbackInterval; } @property CGFloat strokeWidth; @property CGFloat strokeAlpha; @property CGColorRef strokeColor; @property bool erase; -@property (nonatomic, assign) id delegate; +@property(nonatomic, assign) id delegate; - (void)drawInContext:(CGContextRef)context andApplyErase:(bool)applyErase; +- (void)clear; +- (void)undo; +- (void)redo; +- (void)bakeStrokesToDelegate; -@end \ No newline at end of file +// Playback methods +- (void)playbackDrawing:(NSTimeInterval)duration; +- (void)pausePlayback; +- (void)resumePlayback; +- (void)stopPlayback; +- (void)setPlaybackSpeed:(CGFloat)speed; +- (CGFloat)getPlaybackProgress; + +// Save/Load methods +- (NSArray *)getStrokesData; +- (void)loadStrokes:(NSArray *)strokesArray; + +@end diff --git a/ios/Classes/WetPaintView.m b/ios/Classes/WetPaintView.m index e87577f..5957c4b 100644 --- a/ios/Classes/WetPaintView.m +++ b/ios/Classes/WetPaintView.m @@ -24,134 +24,482 @@ @implementation WetPaintView #pragma mark Lifecycle -- (id)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - self.multipleTouchEnabled = YES; - strokeWidth = 5; - strokeAlpha = 1; - strokeColor = CGColorRetain([[TiUtils colorValue:@"#000"] _color].CGColor); - _touchLines = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - self.opaque = NO; - self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0]; - } - return self; +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.multipleTouchEnabled = YES; + strokeWidth = 5; + strokeAlpha = 1; + strokeColor = CGColorRetain([[TiUtils colorValue:@"#000"] _color].CGColor); + _touchLines = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + _completedStrokes = [[NSMutableArray alloc] init]; + _undoStrokes = [[NSMutableArray alloc] init]; + + // Initialize playback state + _playbackStrokes = [[NSMutableArray alloc] init]; + _currentPlaybackIndex = 0; + _isPlayingBack = NO; + _isPaused = NO; + _playbackInterval = 0.1; + + self.opaque = NO; + self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0]; + } + return self; } -- (void)dealloc -{ - CFDictionaryRemoveAllValues(_touchLines); - _touchLines = NULL; - CGColorRelease(strokeColor); - [super dealloc]; +- (void)dealloc { + CFDictionaryRemoveAllValues(_touchLines); + _touchLines = NULL; + CGColorRelease(strokeColor); + [_completedStrokes release]; + [_undoStrokes release]; + [_playbackStrokes release]; + [_playbackTimer invalidate]; + [super dealloc]; } #pragma mark Public API - (void)drawInContext:(CGContextRef)context andApplyErase:(bool)applyErase { - CGContextSetLineCap(context, kCGLineCapRound); + CGContextSetLineCap(context, kCGLineCapRound); + + // Choose which strokes to draw based on playback state + NSArray *strokesToDraw = + _isPlayingBack ? _playbackStrokes : _completedStrokes; + + // Draw strokes + for (NSDictionary *stroke in strokesToDraw) { + NSMutableArray *points = [stroke objectForKey:@"points"]; + CGFloat width = [[stroke objectForKey:@"strokeWidth"] floatValue]; + CGFloat alpha = [[stroke objectForKey:@"strokeAlpha"] floatValue]; + CGColorRef color = (CGColorRef)[stroke objectForKey:@"strokeColor"]; + bool eraseMode = [[stroke objectForKey:@"erase"] boolValue]; + + CGContextSetLineWidth(context, width); + CGContextSetStrokeColorWithColor(context, color); + + if (!eraseMode) { + CGContextSetAlpha(context, alpha); + CGContextSetBlendMode(context, kCGBlendModeNormal); + } else { + // Erase mode: clear pixels (ignore applyErase parameter) + CGContextSetBlendMode(context, kCGBlendModeClear); + } + + [self drawPointsArray:points inContext:context]; + } + + // Draw current active strokes only if not in playback mode + if (!_isPlayingBack) { CGContextSetLineWidth(context, strokeWidth); CGContextSetStrokeColorWithColor(context, strokeColor); if (!erase) { - CGContextSetAlpha(context, strokeAlpha); - CGContextSetBlendMode(context, kCGBlendModeNormal); - CFDictionaryApplyFunction(_touchLines, drawPoints, context); + CGContextSetAlpha(context, strokeAlpha); + CGContextSetBlendMode(context, kCGBlendModeNormal); + CFDictionaryApplyFunction(_touchLines, drawPoints, context); } else if (applyErase) { - CGContextSetBlendMode(context, kCGBlendModeClear); - CFDictionaryApplyFunction(_touchLines, drawPoints, context); + CGContextSetBlendMode(context, kCGBlendModeClear); + CFDictionaryApplyFunction(_touchLines, drawPoints, context); } else { - CGContextSetAlpha(context, 1); // Erasing does not respect alpha, unfortunately. - CGContextSetStrokeColorWithColor(context, [[TiUtils colorValue:@"#000"] _color].CGColor); - CFDictionaryApplyFunction(_touchLines, drawPoints, context); + // Show erase strokes with user's chosen color (visual feedback) + CGContextSetAlpha(context, strokeAlpha); + CGContextSetStrokeColorWithColor(context, strokeColor); + CGContextSetBlendMode(context, kCGBlendModeNormal); + CFDictionaryApplyFunction(_touchLines, drawPoints, context); } + } } #pragma mark Drawing -- (void)drawRect:(CGRect)rect -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - [self drawInContext:context andApplyErase:NO]; - UIGraphicsEndImageContext(); +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + [self drawInContext:context andApplyErase:NO]; + UIGraphicsEndImageContext(); } #pragma mark Drawing Utility -static void drawPoints(const void* key, const void* value, void* ctx) -{ - CGContextRef context = ctx; - NSMutableArray* points = (NSMutableArray*)value; - if (points == nil || [points count] == 0) { - return; +static void drawPoints(const void *key, const void *value, void *ctx) { + CGContextRef context = ctx; + NSMutableArray *points = (NSMutableArray *)value; + if (points == nil || [points count] == 0) { + return; + } + CGPoint first = [[points objectAtIndex:0] CGPointValue]; + CGContextBeginPath(context); + CGContextMoveToPoint(context, first.x, first.y); + NSValue *lastValue = nil; + for (NSValue *value in points) { + CGPoint point = [value CGPointValue]; + if (lastValue != nil) { + CGPoint lastPoint = [lastValue CGPointValue]; + CGContextAddQuadCurveToPoint(context, lastPoint.x, lastPoint.y, + (point.x + lastPoint.x) / 2, + (point.y + lastPoint.y) / 2); } - CGPoint first = [[points objectAtIndex:0] CGPointValue]; - CGContextBeginPath(context); - CGContextMoveToPoint(context, first.x, first.y); - NSValue* lastValue = nil; - for (NSValue* value in points) { - CGPoint point = [value CGPointValue]; - if (lastValue != nil) { - CGPoint lastPoint = [lastValue CGPointValue]; - CGContextAddQuadCurveToPoint(context, lastPoint.x, lastPoint.y, (point.x + lastPoint.x) / 2, (point.y + lastPoint.y) / 2); - } - lastValue = value; + lastValue = value; + } + CGContextStrokePath(context); +} + +- (void)drawPointsArray:(NSMutableArray *)points + inContext:(CGContextRef)context { + if (points == nil || [points count] == 0) { + return; + } + CGPoint first = [[points objectAtIndex:0] CGPointValue]; + CGContextBeginPath(context); + CGContextMoveToPoint(context, first.x, first.y); + NSValue *lastValue = nil; + for (NSValue *value in points) { + CGPoint point = [value CGPointValue]; + if (lastValue != nil) { + CGPoint lastPoint = [lastValue CGPointValue]; + CGContextAddQuadCurveToPoint(context, lastPoint.x, lastPoint.y, + (point.x + lastPoint.x) / 2, + (point.y + lastPoint.y) / 2); } - CGContextStrokePath(context); + lastValue = value; + } + CGContextStrokePath(context); } #pragma mark Touch Delegate -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - for (UITouch* touch in [touches allObjects]) { - CGPoint point = [touch locationInView:self]; - NSValue* value = [NSValue valueWithCGPoint:point]; - NSMutableArray* points = [[NSMutableArray arrayWithObject:value] retain]; - CFDictionarySetValue(_touchLines, touch, points); - } - [super touchesBegan:touches withEvent:event]; +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + // Clear redo history when new stroke starts + [_undoStrokes removeAllObjects]; + + for (UITouch *touch in [touches allObjects]) { + CGPoint point = [touch locationInView:self]; + NSValue *value = [NSValue valueWithCGPoint:point]; + NSMutableArray *points = [[NSMutableArray arrayWithObject:value] retain]; + CFDictionarySetValue(_touchLines, touch, points); + } + [super touchesBegan:touches withEvent:event]; } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - for (UITouch* touch in [touches allObjects]) { - NSMutableArray* points = (NSMutableArray*)CFDictionaryGetValue(_touchLines, touch); - CGPoint point = [touch locationInView:self]; - NSValue* value = [NSValue valueWithCGPoint:point]; - [points addObject:value]; - } +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in [touches allObjects]) { + NSMutableArray *points = + (NSMutableArray *)CFDictionaryGetValue(_touchLines, touch); + CGPoint point = [touch locationInView:self]; + NSValue *value = [NSValue valueWithCGPoint:point]; + [points addObject:value]; + } + [self setNeedsDisplay]; + [super touchesMoved:touches withEvent:event]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in [touches allObjects]) { + CFDictionaryRemoveValue(_touchLines, touch); + } + [self setNeedsDisplay]; + [super touchesCancelled:touches withEvent:event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in [touches allObjects]) { + NSMutableArray *points = + (NSMutableArray *)CFDictionaryGetValue(_touchLines, touch); + CGPoint point = [touch locationInView:self]; + NSValue *value = [NSValue valueWithCGPoint:point]; + [points addObject:value]; + + // Save completed stroke to array instead of immediately baking + NSDictionary *stroke = [NSDictionary + dictionaryWithObjectsAndKeys:[NSMutableArray arrayWithArray:points], + @"points", + [NSNumber numberWithFloat:strokeWidth], + @"strokeWidth", + [NSNumber numberWithFloat:strokeAlpha], + @"strokeAlpha", (id)strokeColor, + @"strokeColor", + [NSNumber numberWithBool:erase], @"erase", + nil]; + [_completedStrokes addObject:stroke]; + } + + // NOTE: We DON'T call readyToSavePaint here anymore + // It will be called only when we actually need to bake the image + + for (UITouch *touch in [touches allObjects]) { + CFDictionaryRemoveValue(_touchLines, touch); + } + [self setNeedsDisplay]; + [super touchesEnded:touches withEvent:event]; +} + +#pragma mark Clear/Undo/Redo + +- (void)clear { + [_completedStrokes removeAllObjects]; + [_undoStrokes removeAllObjects]; + CFDictionaryRemoveAllValues(_touchLines); + [self setNeedsDisplay]; +} + +- (void)undo { + if ([_completedStrokes count] > 0) { + NSDictionary *lastStroke = [_completedStrokes lastObject]; + [_undoStrokes addObject:lastStroke]; + [_completedStrokes removeLastObject]; [self setNeedsDisplay]; - [super touchesMoved:touches withEvent:event]; + } } -- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - for (UITouch* touch in [touches allObjects]) { - CFDictionaryRemoveValue(_touchLines, touch); - } +- (void)redo { + if ([_undoStrokes count] > 0) { + NSDictionary *lastUndoStroke = [_undoStrokes lastObject]; + [_completedStrokes addObject:lastUndoStroke]; + [_undoStrokes removeLastObject]; [self setNeedsDisplay]; - [super touchesCancelled:touches withEvent:event]; + } } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - for (UITouch* touch in [touches allObjects]) { - NSMutableArray* points = (NSMutableArray*)CFDictionaryGetValue(_touchLines, touch); - CGPoint point = [touch locationInView:self]; - NSValue* value = [NSValue valueWithCGPoint:point]; - [points addObject:value]; +// Method to force baking when needed +- (void)bakeStrokesToDelegate { + if (delegate != nil && + [delegate respondsToSelector:@selector(readyToSavePaint)]) { + [delegate readyToSavePaint]; + } +} + +#pragma mark Playback Methods + +- (void)playbackDrawing:(NSTimeInterval)duration { + if ([_completedStrokes count] == 0) + return; + + [self stopPlayback]; // Stop any existing playback + + _isPlayingBack = YES; + _isPaused = NO; + _currentPlaybackIndex = 0; + [_playbackStrokes removeAllObjects]; + + _playbackInterval = duration / [_completedStrokes count]; + // Ensure reasonable maximum interval (no more than 1 second between strokes) + if (_playbackInterval > 1.0) { + _playbackInterval = 1.0; + } + + _playbackTimer = [NSTimer + scheduledTimerWithTimeInterval:_playbackInterval + repeats:YES + block:^(NSTimer *timer) { + if (self->_currentPlaybackIndex < + [self->_completedStrokes count] && + self->_isPlayingBack && !self->_isPaused) { + [self->_playbackStrokes + addObject: + [self->_completedStrokes + objectAtIndex: + self-> + _currentPlaybackIndex]]; + self->_currentPlaybackIndex++; + [self setNeedsDisplay]; + } else if (self->_currentPlaybackIndex >= + [self->_completedStrokes count]) { + [self stopPlayback]; + } + }]; +} + +- (void)pausePlayback { + _isPaused = YES; +} + +- (void)resumePlayback { + _isPaused = NO; +} + +- (void)stopPlayback { + [_playbackTimer invalidate]; + _playbackTimer = nil; + _isPlayingBack = NO; + _isPaused = NO; + _currentPlaybackIndex = 0; + [_playbackStrokes removeAllObjects]; + [self setNeedsDisplay]; +} + +- (void)setPlaybackSpeed:(CGFloat)speed { + if (_playbackTimer && _isPlayingBack) { + NSTimeInterval newInterval = (_playbackInterval / speed); + [_playbackTimer invalidate]; + + _playbackTimer = [NSTimer + scheduledTimerWithTimeInterval:newInterval + repeats:YES + block:^(NSTimer *timer) { + if (self->_currentPlaybackIndex < + [self->_completedStrokes count] && + self->_isPlayingBack && + !self->_isPaused) { + [self->_playbackStrokes + addObject: + [self->_completedStrokes + objectAtIndex: + self-> + _currentPlaybackIndex]]; + self->_currentPlaybackIndex++; + [self setNeedsDisplay]; + } else if (self->_currentPlaybackIndex >= + [self->_completedStrokes count]) { + [self stopPlayback]; + } + }]; + } +} + +- (CGFloat)getPlaybackProgress { + if ([_completedStrokes count] == 0) + return 0.0; + return (CGFloat)_currentPlaybackIndex / (CGFloat)[_completedStrokes count]; +} + +#pragma mark Save/Load Methods + +- (NSArray *)getStrokesData { + NSMutableArray *strokesData = [[NSMutableArray alloc] init]; + + for (NSDictionary *stroke in _completedStrokes) { + NSMutableDictionary *strokeData = [[NSMutableDictionary alloc] init]; + + // Get stroke properties + NSArray *points = [stroke objectForKey:@"points"]; + NSNumber *width = [stroke objectForKey:@"strokeWidth"]; + NSNumber *alpha = [stroke objectForKey:@"strokeAlpha"]; + id colorObj = [stroke objectForKey:@"strokeColor"]; + NSNumber *isErase = [stroke objectForKey:@"erase"]; + + if (points) { + NSMutableArray *pointsArray = [[NSMutableArray alloc] init]; + for (NSValue *pointValue in points) { + CGPoint point = [pointValue CGPointValue]; + NSDictionary *pointDict = @{@"x" : @(point.x), @"y" : @(point.y)}; + [pointsArray addObject:pointDict]; + } + [strokeData setObject:pointsArray forKey:@"points"]; } - - if (delegate != nil && [delegate respondsToSelector:@selector(readyToSavePaint)]) { - [delegate readyToSavePaint]; + if (width) + [strokeData setObject:width forKey:@"strokeWidth"]; + if (alpha) + [strokeData setObject:alpha forKey:@"strokeAlpha"]; + [strokeData setObject:(isErase ? isErase : @(NO)) forKey:@"eraseMode"]; + + // Convert CGColor to hex string + if (colorObj) { + CGColorRef color = (__bridge CGColorRef)colorObj; + const CGFloat *components = CGColorGetComponents(color); + size_t numComponents = CGColorGetNumberOfComponents(color); + + int red = 0, green = 0, blue = 0; + if (numComponents >= 3) { + red = (int)(components[0] * 255); + green = (int)(components[1] * 255); + blue = (int)(components[2] * 255); + } else if (numComponents >= 1) { + // Grayscale color + red = green = blue = (int)(components[0] * 255); + } + + NSString *hexColor = + [NSString stringWithFormat:@"#%02x%02x%02x", red, green, blue]; + [strokeData setObject:hexColor forKey:@"strokeColor"]; + } else { + [strokeData setObject:@"#000000" forKey:@"strokeColor"]; } - - for (UITouch* touch in [touches allObjects]) { - CFDictionaryRemoveValue(_touchLines, touch); + + [strokesData addObject:strokeData]; + } + + return strokesData; +} + +- (void)loadStrokes:(NSArray *)strokesArray { + [_completedStrokes removeAllObjects]; + [_undoStrokes removeAllObjects]; + + for (NSDictionary *strokeData in strokesArray) { + NSMutableDictionary *stroke = [[NSMutableDictionary alloc] init]; + + // Get stroke data + NSArray *points = [strokeData objectForKey:@"points"]; + NSNumber *width = [strokeData objectForKey:@"strokeWidth"]; + NSNumber *alpha = [strokeData objectForKey:@"strokeAlpha"]; + NSString *hexColor = [strokeData objectForKey:@"strokeColor"]; + NSNumber *isErase = [strokeData objectForKey:@"eraseMode"]; + + if (points) { + NSMutableArray *pointsArray = [[NSMutableArray alloc] init]; + for (NSDictionary *pointDict in points) { + CGFloat x = [[pointDict objectForKey:@"x"] floatValue]; + CGFloat y = [[pointDict objectForKey:@"y"] floatValue]; + CGPoint point = CGPointMake(x, y); + [pointsArray addObject:[NSValue valueWithCGPoint:point]]; + } + [stroke setObject:pointsArray forKey:@"points"]; } - [self setNeedsDisplay]; - [super touchesEnded:touches withEvent:event]; + if (width) + [stroke setObject:width forKey:@"strokeWidth"]; + if (alpha) + [stroke setObject:alpha forKey:@"strokeAlpha"]; + if (isErase) + [stroke setObject:isErase forKey:@"erase"]; + + // Convert hex string to CGColor + if (hexColor) { + UIColor *uiColor = [self colorFromHexString:hexColor]; + [stroke setObject:(__bridge id)[uiColor CGColor] forKey:@"strokeColor"]; + } + + [_completedStrokes addObject:stroke]; + } + + [self setNeedsDisplay]; +} + +- (UIColor *)colorFromHexString:(NSString *)hexString { + NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@"#" + withString:@""]; + if ([cleanString length] == 3) { + cleanString = [NSString + stringWithFormat:@"%@%@%@%@%@%@", + [cleanString substringWithRange:NSMakeRange(0, 1)], + [cleanString substringWithRange:NSMakeRange(0, 1)], + [cleanString substringWithRange:NSMakeRange(1, 1)], + [cleanString substringWithRange:NSMakeRange(1, 1)], + [cleanString substringWithRange:NSMakeRange(2, 1)], + [cleanString substringWithRange:NSMakeRange(2, 1)]]; + } + if ([cleanString length] == 6) { + cleanString = [cleanString stringByAppendingString:@"ff"]; + } + + unsigned int baseValue; + [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue]; + + float red = ((baseValue >> 24) & 0xFF) / 255.0f; + float green = ((baseValue >> 16) & 0xFF) / 255.0f; + float blue = ((baseValue >> 8) & 0xFF) / 255.0f; + float alpha = ((baseValue >> 0) & 0xFF) / 255.0f; + + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + +#pragma mark - UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + if ([gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) { + return NO; + } + return YES; } @end diff --git a/ios/manifest b/ios/manifest index 066812b..ec73255 100644 --- a/ios/manifest +++ b/ios/manifest @@ -2,13 +2,13 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 1.4.2 +version: 2.0.0 apiversion: 2 -architectures: armv7 i386 x86_64 arm64 -description: Provides a paint surface user interface view. -author: Jeff Haynie -license: Appcelerator Commercial License -copyright: Copyright (c) 2010-Present by Appcelerator, Inc. +architectures: arm64 x86_64 +description: Provides a paint surface user interface view with undo/redo and playback functionality. +author: Jeff Haynie +license: Appcelerator Commercial License +copyright: Copyright (c) 2010-Present by Appcelerator, Inc. # these should not be edited @@ -16,4 +16,4 @@ name: paint moduleid: ti.paint guid: 43f13063-d426-4e9c-8a7a-72dc5e4aec57 platform: iphone -minsdk: 5.0.0 +minsdk: 13.0.0 diff --git a/ios/paint.xcodeproj/project.pbxproj b/ios/paint.xcodeproj/project.pbxproj index 173f16f..885414a 100644 --- a/ios/paint.xcodeproj/project.pbxproj +++ b/ios/paint.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 52; objects = { /* Begin PBXAggregateTarget section */ @@ -170,14 +170,15 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 1410; }; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "paint" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 11.0"; + developmentRegion = en; hasScannedForEncodings = 1; knownRegions = ( en, + Base, ); mainGroup = 0867D691FE84028FC02AAC07 /* paint */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; @@ -234,8 +235,10 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DSTROOT = /tmp/TiPaint.dst; @@ -256,7 +259,7 @@ GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_CFLAGS = ( "-DDEBUG", "-DTI_POST_1_2", @@ -278,6 +281,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_WEAK = YES; DSTROOT = /tmp/TiPaint.dst; GCC_C_LANGUAGE_STANDARD = c99; GCC_MODEL_TUNING = G5; @@ -296,8 +300,8 @@ GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - "IPHONEOS_DEPLOYMENT_TARGET[sdk=iphonesimulator*]" = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + "IPHONEOS_DEPLOYMENT_TARGET[sdk=iphonesimulator*]" = 15.0; OTHER_CFLAGS = "-DTI_POST_1_2"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = TiPaint; @@ -314,10 +318,32 @@ ARCHS = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DSTROOT = /tmp/TiPaint.dst; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TiPaint_Prefix.pch; @@ -325,16 +351,19 @@ GCC_THUMB_SUPPORT = NO; GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = NO; GCC_WARN_MISSING_PARENTHESES = NO; GCC_WARN_SHADOW = NO; GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-DDEBUG", @@ -358,25 +387,49 @@ ARCHS = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; DSTROOT = /tmp/TiPaint.dst; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_MODEL_TUNING = G5; + GCC_NO_COMMON_BLOCKS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TiPaint_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; GCC_THUMB_SUPPORT = NO; GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = NO; GCC_WARN_MISSING_PARENTHESES = NO; GCC_WARN_SHADOW = NO; GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_CFLAGS = "-DTI_POST_1_2"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = TiPaint; @@ -390,6 +443,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -402,9 +456,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_THUMB_SUPPORT = NO; PRODUCT_NAME = "Build & test"; ZERO_LINK = NO; diff --git a/ios/timodule.xml b/ios/timodule.xml new file mode 100644 index 0000000..feea636 --- /dev/null +++ b/ios/timodule.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/ios/titanium.xcconfig b/ios/titanium.xcconfig index e41f6ab..df2584d 100644 --- a/ios/titanium.xcconfig +++ b/ios/titanium.xcconfig @@ -4,16 +4,11 @@ // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR // // -TITANIUM_SDK_VERSION = 6.0.0.GA +TITANIUM_SDK_VERSION = 12.8.0.GA - -// +// // THESE SHOULD BE OK GENERALLY AS-IS // -TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) -TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" -TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" -HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) ~$(TITANIUM_BASE_SDK) ~$(TITANIUM_BASE_SDK2) - - - +TITANIUM_SDK = /Users/$(USER)/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) +HEADER_SEARCH_PATHS = $(inherited) "$(TITANIUM_SDK)/iphone/include" +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(TITANIUM_SDK)/iphone/Frameworks/**" diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt deleted file mode 100644 index 13a21bd..0000000 --- a/windows/CMakeLists.txt +++ /dev/null @@ -1,121 +0,0 @@ -# Titanium Windows Native Module - ti.paint -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -cmake_minimum_required(VERSION 3.0.0) - -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows10") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) - add_definitions("-DPHONE") -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -project(TiPaint) - -set(TiPaint_VERSION 0.1.0) - -set(WINDOWS_SOURCE_DIR "C:/ProgramData/Titanium/mobilesdk/win32/8.0.0.GA/windows") - -SET(CMAKE_FIND_LIBRARY_PREFIXES "") -SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll") - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) - -option(TiPaint_DISABLE_TESTS "Disable compiling the tests" OFF) - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -get_filename_component(APPCELERATOR_CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ABSOLUTE) -list(INSERT CMAKE_MODULE_PATH 0 ${APPCELERATOR_CMAKE_MODULE_PATH}) - -find_package(HAL REQUIRED) -find_package(TitaniumKit REQUIRED) -find_package(LayoutEngine REQUIRED) -find_package(TitaniumWindows_UI REQUIRED) -find_package(JavaScriptCore REQUIRED) - -enable_testing() - -set(SOURCE_TiPaint - include/TiPaint.hpp - src/TiPaint.cpp - include/TiPaintView.hpp - src/TiPaintView.cpp - ) - -source_group(TiPaint FILES ${SOURCE_TiPaint}) - -set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) - -add_library(TiPaint SHARED - ${SOURCE_TiPaint} - ) - -include(GenerateExportHeader) -generate_export_header(TiPaint) -target_compile_definitions(TiPaint PRIVATE TiPaint_EXPORTS) - -target_include_directories(TiPaint PUBLIC - ${PROJECT_SOURCE_DIR}/include - $ - $ - $ - $ - ) - -target_link_libraries(TiPaint - JavaScriptCore - HAL - TitaniumKit - LayoutEngine - TitaniumWindows_UI - ) - -set_target_properties(TiPaint PROPERTIES VS_WINRT_COMPONENT TRUE) - -set_property(TARGET TiPaint APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF") - -if (NOT TiPaint_DISABLE_TESTS) - add_subdirectory(test) -endif() - -set_property(TARGET TiPaint PROPERTY VERSION ${TiPaint_VERSION}) -set_property(TARGET TiPaint PROPERTY SOVERSION 0) -set_property(TARGET TiPaint PROPERTY INTERFACE_TiPaint_MAJOR_VERSION 0) -set_property(TARGET TiPaint APPEND PROPERTY - COMPATIBLE_INTERFACE_STRING TiPaint_MAJOR_VERSION - ) - -install(TARGETS TiPaint EXPORT TiPaint_Targets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include - ) - -export(EXPORT TiPaint_Targets - FILE "${CMAKE_BINARY_DIR}/TiPaint_Targets.cmake" -) - -configure_file(cmake/TiPaint_Config.cmake - "${CMAKE_BINARY_DIR}/TiPaint_Config.cmake" - COPYONLY - ) - -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - "${CMAKE_BINARY_DIR}/TiPaint_ConfigVersion.cmake" - VERSION ${TiPaint_VERSION} - COMPATIBILITY AnyNewerVersion - ) - -export(PACKAGE TiPaint) diff --git a/windows/cmake/FindHAL.cmake b/windows/cmake/FindHAL.cmake deleted file mode 100644 index 4a7b24f..0000000 --- a/windows/cmake/FindHAL.cmake +++ /dev/null @@ -1,95 +0,0 @@ -# FindHAL -# Author: Chris Williams -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -# Author: Chris Williams -# Created: 2014.12.02 - - -# Generated by CMake 3.1.3 - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget HAL) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - -if (${CMAKE_SYSTEM_VERSION} MATCHES "^10.0") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -set(HAL_ARCH "x86") -if(CMAKE_GENERATOR MATCHES "^Visual Studio .+ ARM$") - set(HAL_ARCH "arm") -endif() - -# Taken and slightly modified from build's HAL_Targets.cmake file -# INTERFACE_INCLUDE_DIRECTORIES is modified to point to our pre-packaged include dir for module - -# Create imported target HAL -add_library(HAL SHARED IMPORTED) - -set_target_properties(HAL PROPERTIES - COMPATIBLE_INTERFACE_STRING "HAL_MAJOR_VERSION" - INTERFACE_INCLUDE_DIRECTORIES "${WINDOWS_SOURCE_DIR}/lib/HAL/include" - INTERFACE_HAL_MAJOR_VERSION "0" -) - -if (HAL_RENAME_AXWAYHAL) - set_target_properties(HAL PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/HAL/${PLATFORM}/${HAL_ARCH}/AXWAYHAL.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/HAL/${PLATFORM}/${HAL_ARCH}/AXWAYHAL.dll" - ) -else() - set_target_properties(HAL PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/HAL/${PLATFORM}/${HAL_ARCH}/HAL.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/HAL/${PLATFORM}/${HAL_ARCH}/HAL.dll" - ) -endif() - -# This file does not depend on other imported targets which have -# been exported from the same project but in a separate export set. - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff --git a/windows/cmake/FindJavascriptCore.cmake b/windows/cmake/FindJavascriptCore.cmake deleted file mode 100644 index 07b6b94..0000000 --- a/windows/cmake/FindJavascriptCore.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# FindJavaScriptCore -# Author: Chris Williams -# -# Copyright (c) 2017 by Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -# Author: Chris Williams -# Created: 2014.12.02 - -if (${CMAKE_SYSTEM_VERSION} MATCHES "^10.0") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -set(JavaScriptCore_ARCH "x86") -if(CMAKE_GENERATOR MATCHES "^Visual Studio .+ ARM$") - set(JavaScriptCore_ARCH "arm") -endif() - -# Taken and slightly modified from build's JavaScriptCore_Targets.cmake file -# INTERFACE_INCLUDE_DIRECTORIES is modified to point to our pre-packaged include dir for module - -# Create imported target JavaScriptCore -add_library(JavaScriptCore SHARED IMPORTED) - -set_target_properties(JavaScriptCore PROPERTIES - COMPATIBLE_INTERFACE_STRING "JavaScriptCore_MAJOR_VERSION" - INTERFACE_JavaScriptCore_MAJOR_VERSION "0" -) - -set_target_properties(JavaScriptCore PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/JavaScriptCore/${PLATFORM}/${JavaScriptCore_ARCH}/JavaScriptCore.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/JavaScriptCore/${PLATFORM}/${JavaScriptCore_ARCH}/JavaScriptCore.dll" - ) diff --git a/windows/cmake/FindLayoutEngine.cmake b/windows/cmake/FindLayoutEngine.cmake deleted file mode 100644 index 1f5c52b..0000000 --- a/windows/cmake/FindLayoutEngine.cmake +++ /dev/null @@ -1,85 +0,0 @@ -# FindLayoutEngine -# Author: Chris Williams -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -# Author: Chris Williams -# Created: 2014.12.02 - -# Generated by CMake 3.1.3 - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget LayoutEngine) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - - -if (${CMAKE_SYSTEM_VERSION} MATCHES "^10.0") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -set(LayoutEngine_ARCH "x86") -if(CMAKE_GENERATOR MATCHES "^Visual Studio .+ ARM$") - set(LayoutEngine_ARCH "arm") -endif() - -# Taken and slightly modified from build's LayoutEngine_Targets.cmake file -# INTERFACE_INCLUDE_DIRECTORIES is modified to point to our pre-packaged include dir for module - -# Create imported target LayoutEngine -add_library(LayoutEngine SHARED IMPORTED) - -set_target_properties(LayoutEngine PROPERTIES - COMPATIBLE_INTERFACE_STRING "LayoutEngine_MAJOR_VERSION" - INTERFACE_INCLUDE_DIRECTORIES "${WINDOWS_SOURCE_DIR}/lib/LayoutEngine/include;$" - INTERFACE_LINK_LIBRARIES "HAL" - INTERFACE_LayoutEngine_MAJOR_VERSION "0" -) -set_target_properties(LayoutEngine PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/LayoutEngine/${PLATFORM}/${LayoutEngine_ARCH}/LayoutEngine.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/LayoutEngine/${PLATFORM}/${LayoutEngine_ARCH}/LayoutEngine.dll" - ) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff --git a/windows/cmake/FindTitaniumKit.cmake b/windows/cmake/FindTitaniumKit.cmake deleted file mode 100644 index 16714fb..0000000 --- a/windows/cmake/FindTitaniumKit.cmake +++ /dev/null @@ -1,104 +0,0 @@ -# FindTitaniumKit -# Author: Chris Williams -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -# Author: Chris Williams -# Created: 2014.12.02 - -# Generated by CMake 3.1.3 - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget TitaniumKit) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - - -if (${CMAKE_SYSTEM_VERSION} MATCHES "^10.0") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -set(TitaniumKit_ARCH "x86") -if(CMAKE_GENERATOR MATCHES "^Visual Studio .+ ARM$") - set(TitaniumKit_ARCH "arm") -endif() - -# Taken and slightly modified from build's TitaniumKit_Targets.cmake file -# INTERFACE_INCLUDE_DIRECTORIES is modified to point to our pre-packaged include dir for module - -# Create imported target TitaniumKit -add_library(TitaniumKit SHARED IMPORTED) - -set_target_properties(TitaniumKit PROPERTIES - COMPATIBLE_INTERFACE_STRING "TitaniumKit_MAJOR_VERSION" - INTERFACE_INCLUDE_DIRECTORIES "${WINDOWS_SOURCE_DIR}/lib/TitaniumKit/include;$" - INTERFACE_LINK_LIBRARIES "HAL" - INTERFACE_TitaniumKit_MAJOR_VERSION "0" -) -set_target_properties(TitaniumKit PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/TitaniumKit/${PLATFORM}/${TitaniumKit_ARCH}/TitaniumKit.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/TitaniumKit/${PLATFORM}/${TitaniumKit_ARCH}/TitaniumKit.dll" - ) - -# Make sure the targets which have been exported in some other -# export set exist. -unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets) -foreach(_target "HAL" ) - if(NOT TARGET "${_target}" ) - set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}") - endif() -endforeach() - -if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets) - if(CMAKE_FIND_PACKAGE_NAME) - set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) - set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}") - else() - message(FATAL_ERROR "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}") - endif() -endif() -unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) diff --git a/windows/cmake/FindTitaniumWindows_UI.cmake b/windows/cmake/FindTitaniumWindows_UI.cmake deleted file mode 100644 index 2a30d42..0000000 --- a/windows/cmake/FindTitaniumWindows_UI.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# FindTitaniumWindows_UI -# Author: Chris Williams -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -# Author: Chris Williams -# Created: 2014.12.02 - -if (${CMAKE_SYSTEM_VERSION} MATCHES "^10.0") - set(PLATFORM win10) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsPhone") - set(PLATFORM phone) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore") - set(PLATFORM store) -else() - message(FATAL_ERROR "This app supports Store / Phone only.") -endif() - -set(TitaniumWindows_UI_ARCH "x86") -if(CMAKE_GENERATOR MATCHES "^Visual Studio .+ ARM$") - set(TitaniumWindows_UI_ARCH "arm") -endif() - -# Taken and slightly modified from bUtilityld's TitaniumWindows_UI_Targets.cmake file -# INTERFACE_INCLUDE_DIRECTORIES is modified to point to our pre-packaged include dir for module - -# Create imported target TitaniumWindows_UI -add_library(TitaniumWindows_UI SHARED IMPORTED) - -set_target_properties(TitaniumWindows_UI PROPERTIES - COMPATIBLE_INTERFACE_STRING "TitaniumWindows_UI_MAJOR_VERSION" - INTERFACE_INCLUDE_DIRECTORIES "${WINDOWS_SOURCE_DIR}/lib/TitaniumWindows_UI/include;$" - INTERFACE_LINK_LIBRARIES "TitaniumKit" - INTERFACE_TitaniumWindows_UI_MAJOR_VERSION "0" -) - -set_target_properties(TitaniumWindows_UI PROPERTIES - IMPORTED_IMPLIB "${WINDOWS_SOURCE_DIR}/lib/TitaniumWindows_UI/${PLATFORM}/${TitaniumWindows_UI_ARCH}/TitaniumWindows_UI.lib" - IMPORTED_LOCATION "${WINDOWS_SOURCE_DIR}/lib/TitaniumWindows_UI/${PLATFORM}/${TitaniumWindows_UI_ARCH}/TitaniumWindows_UI.dll" - ) diff --git a/windows/cmake/TiPaint_Config.cmake b/windows/cmake/TiPaint_Config.cmake deleted file mode 100644 index 7342ffb..0000000 --- a/windows/cmake/TiPaint_Config.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# Titanium Windows Native Module - ti.paint -# -# Copyright (c) 2017 Axway All Rights Reserved. -# Licensed under the terms of the Apache Public License. -# Please see the LICENSE included with this distribution for details. - -include(CMakeFindDependencyMacro) -find_dependency(HAL) -find_dependency(TitaniumKit) - -include("${CMAKE_BINARY_DIR}/TitaniumWindows_TiPaint_Targets.cmake") \ No newline at end of file diff --git a/windows/documentation/changelog.md b/windows/documentation/changelog.md deleted file mode 100644 index 13ae305..0000000 --- a/windows/documentation/changelog.md +++ /dev/null @@ -1,3 +0,0 @@ -# Change Log -
-1.0.0    Initial Windows Release
diff --git a/windows/documentation/index.md b/windows/documentation/index.md
deleted file mode 100644
index f348e3a..0000000
--- a/windows/documentation/index.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Ti.Paint Module
-
-## Description
-
-Provides a paint surface user interface view.
-
-## Accessing the Ti.Paint Module
-
-To access this module from JavaScript, you would do the following:
-
-	var Paint = require('ti.paint');
-
-### Ti.Paint.createPaintView({...})
-
-Creates a [Ti.Paint.PaintView][] object.
-
-#### Arguments
-
-* parameters [object] - (optional) a dictionary object properties defined in [Titanium.UI.View][]
-                                                                                                 
-## Module History
-
-View the [change log](changelog.html) for this module.
-
-## Usage
-
-See example
-
-[Ti.Paint.PaintView]: paintView.html
-[Titanium.UI.View]: http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.UI.View-object.html
\ No newline at end of file
diff --git a/windows/documentation/paintView.md b/windows/documentation/paintView.md
deleted file mode 100644
index 1733cac..0000000
--- a/windows/documentation/paintView.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Ti.Paint.PaintView
-
-## Description
-
-A _Ti.Paint_ module object which is a view for painting in.
-
-## Functions
-
-### clear()
-
-Clears the paint view.
-
-## Properties
-
-### strokeWidth[double]
-
-Controls the width of the strokes.
-
-### strokeColor[string]
-
-Controls the color of the strokes.
-
-### strokeAlpha[int]
-
-Controls the opacity of the strokes.
-
-### eraseMode[boolean]
-
-Controls if the strokes are in "erase mode" -- that is, any existing paint will be erased.
-
-### image[string]
-
-Loads an image (by its URL) directly in to the paint view so that it can be drawn on and erased.
\ No newline at end of file
diff --git a/windows/example/app.js b/windows/example/app.js
deleted file mode 100644
index 905ae49..0000000
--- a/windows/example/app.js
+++ /dev/null
@@ -1,55 +0,0 @@
-var win = Ti.UI.createWindow({
-		backgroundColor: 'red',
-		layout: 'vertical'
-	}),
-	control = Ti.UI.createView({
-		backgroundColor: 'gray',
-		layout: 'horizontal',
-		height: Ti.UI.SIZE
-	}),
-	btn_red = Ti.UI.createButton({title: 'RED', backgroundColor: 'red'}),
-	btn_erase = Ti.UI.createButton({title: 'ERASE'}),
-	btn_clear = Ti.UI.createButton({title: 'CLEAR'}),
-	btn_save = Ti.UI.createButton({title: 'SAVE'}),
-	
-	paintView = require('ti.paint').createPaintView({
-		top: 10, bottom: 10,
-		left: 10, right: 10,
-		backgroundColor: 'white',
-		strokeColor: 'black', strokeWidth: 6,
-		width: Ti.UI.FILL, height: '30%'
-	});
-	imageView = Ti.UI.createImageView({
-		top: 10, bottom: 10,
-		left: 10, right: 10,
-		width: Ti.UI.FILL, height: '30%'
-	});
-	
-btn_red.addEventListener('click', function() {
-	paintView.strokeColor = 'red';
-});
-
-btn_erase.addEventListener('click', function() {
-	paintView.eraseMode = !paintView.eraseMode;
-});
-
-btn_clear.addEventListener('click', function() {
-	paintView.clear();
-});
-
-btn_save.addEventListener('click', function() {
-	paintView.toImage(function(blob) {
-		imageView.image = blob;
-	});
-});
-	
-control.add(btn_red);
-control.add(btn_erase);
-control.add(btn_clear);
-control.add(btn_save);
-
-win.add(control);
-win.add(paintView);
-win.add(imageView);
-
-win.open();
\ No newline at end of file
diff --git a/windows/include/TiPaint.hpp b/windows/include/TiPaint.hpp
deleted file mode 100644
index 57a0d8c..0000000
--- a/windows/include/TiPaint.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
-* Titanium Windows - ti.paint
-*
-* Copyright (c) 2017 by Axway All Rights Reserved.
-* Licensed under the terms of the Apache Public License.
-* Please see the LICENSE included with this distribution for details.
-*/
-#ifndef _TIPAINT_HPP_
-#define _TIPAINT_HPP_
-
-#include "TiPaint_EXPORT.h"
-#include "Titanium/Module.hpp"
-#include "Titanium/detail/TiBase.hpp"
-
-namespace Ti
-{
-	using namespace HAL;
-
-	class TIPAINT_EXPORT Paint : public Titanium::Module, public JSExport
-	{
-		public:
-			Paint(const JSContext&) TITANIUM_NOEXCEPT;
-
-			virtual ~Paint()               = default;
-			Paint(const Paint&)            = default;
-			Paint& operator=(const Paint&) = default;
-#ifdef TITANIUM_MOVE_CTOR_AND_ASSIGN_DEFAULT_ENABLE
-			Paint(Paint&&)                 = default;
-			Paint& operator=(Paint&&)      = default;
-#endif
-
-			static void JSExportInitialize();
-
-			TITANIUM_FUNCTION_DEF(createPaintView);
-
-		private:
-			JSClass paintView__;
-	};
-}
-#endif // _TIPAINT_HPP_
diff --git a/windows/include/TiPaintView.hpp b/windows/include/TiPaintView.hpp
deleted file mode 100644
index ad9d16d..0000000
--- a/windows/include/TiPaintView.hpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Titanium Windows - ti.paint
- *
- * Copyright (c) 2017 by Axway All Rights Reserved.
- * Licensed under the terms of the Apache Public License.
- * Please see the LICENSE included with this distribution for details.
- */
-#ifndef _TIPAINTVIEW_HPP_
-#define _TIPAINTVIEW_HPP_
-
-#include "TiPaint_EXPORT.h"
-#include "Titanium/UI/View.hpp"
-#include "Titanium/detail/TiBase.hpp"
-
-namespace Ti
-{
-	using namespace HAL;
-
-	using namespace Windows::Foundation;
-	using namespace Windows::UI::Xaml::Controls;
-	using namespace Windows::UI::Xaml::Media;
-
-	class TIPAINT_EXPORT PaintView : public Titanium::UI::View, public JSExport
-	{
-	public:
-		PaintView(const JSContext&) TITANIUM_NOEXCEPT;
-
-		virtual void postCallAsConstructor(const JSContext& js_context, const std::vector& arguments) override;
-
-		virtual ~PaintView() = default;
-		PaintView(const PaintView&) = default;
-		PaintView& operator=(const PaintView&) = default;
-#ifdef TITANIUM_MOVE_CTOR_AND_ASSIGN_DEFAULT_ENABLE
-		PaintView(PaintView&&) = default;
-		PaintView& operator=(PaintView&&) = default;
-#endif
-
-		static void JSExportInitialize();
-
-		TITANIUM_PROPERTY_DEF(strokeWidth);
-		TITANIUM_PROPERTY_IMPL_DEF(double, strokeWidth);
-
-		TITANIUM_PROPERTY_DEF(strokeColor);
-		TITANIUM_PROPERTY_IMPL_READONLY_DEF(std::string, strokeColor);
-		virtual void set_strokeColor(const std::string& color) TITANIUM_NOEXCEPT;
-
-		TITANIUM_PROPERTY_DEF(strokeAlpha);
-		TITANIUM_PROPERTY_IMPL_READONLY_DEF(int, strokeAlpha);
-		virtual void set_strokeAlpha(const int& color) TITANIUM_NOEXCEPT;
-
-		TITANIUM_PROPERTY_DEF(eraseMode);
-		TITANIUM_PROPERTY_IMPL_DEF(bool, eraseMode);
-
-		TITANIUM_PROPERTY_DEF(image);
-		TITANIUM_PROPERTY_IMPL_DEF(std::string, image);
-
-		TITANIUM_FUNCTION_DEF(clear);
-
-	private:
-#pragma warning(push)
-#pragma warning(disable : 4251)
-		double strokeWidth__;
-		std::string strokeColor__;
-		int strokeAlpha__;
-		bool eraseMode__;
-		std::string image__;
-
-		std::uint32_t inputId__;
-		Point inputStart__;
-		Point inputEnd__;
-		Brush^ strokeBrush__{ nullptr };
-		Canvas^ canvas__{ nullptr };
-#pragma warning(pop)
-	};
-}
-#endif // _TIPAINTVIEW_HPP_
diff --git a/windows/manifest b/windows/manifest
deleted file mode 100644
index 2db31dc..0000000
--- a/windows/manifest
+++ /dev/null
@@ -1,15 +0,0 @@
-version: 3.3.0
-apiversion: 7
-architectures: ARM x86
-description: Provides a paint surface user interface view.
-author: Gary Mathews
-license: Appcelerator Commercial License
-copyright: Copyright (c) 2017 Axway
-
-# these should not be edited
-name: ti.paint
-moduleid: ti.paint
-moduleIdAsIdentifier: TiPaint
-guid: 3a8ff336-741e-4a70-bb0c-01a4e44574e9
-platform: windows
-minsdk: 8.0.0
diff --git a/windows/src/TiPaint.cpp b/windows/src/TiPaint.cpp
deleted file mode 100644
index ab748c4..0000000
--- a/windows/src/TiPaint.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-* Titanium Windows - ti.paint
-*
-* Copyright (c) 2017 by Axway All Rights Reserved.
-* Licensed under the terms of the Apache Public License.
-* Please see the LICENSE included with this distribution for details.
-*/
-#include "TiPaint.hpp"
-#include "TiPaintView.hpp"
-
-namespace Ti
-{
-	Paint::Paint(const JSContext& js_context) TITANIUM_NOEXCEPT
-		: Titanium::Module(js_context, "ti.paint"),
-		paintView__(JSExport::Class())
-	{
-		TITANIUM_LOG_DEBUG("Ti::Paint::ctor Initialize");
-	}
-
-	void Paint::JSExportInitialize()
-	{
-		JSExport::SetClassVersion(1);
-		JSExport::SetParent(JSExport::Class());
-
-		TITANIUM_ADD_FUNCTION(Paint, createPaintView);
-	}
-
-	TITANIUM_FUNCTION(Paint, createPaintView)
-	{
-		ENSURE_OPTIONAL_OBJECT_AT_INDEX(parameters, 0);
-		auto paintView_obj = get_context().CreateObject(paintView__).CallAsConstructor(parameters);
-		Titanium::Module::applyProperties(parameters, paintView_obj);
-		return paintView_obj;
-	}
-
-}
diff --git a/windows/src/TiPaintView.cpp b/windows/src/TiPaintView.cpp
deleted file mode 100644
index 2899675..0000000
--- a/windows/src/TiPaintView.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
-* Titanium Windows - ti.paint
-*
-* Copyright (c) 2017 by Axway All Rights Reserved.
-* Licensed under the terms of the Apache Public License.
-* Please see the LICENSE included with this distribution for details.
-*/
-#include "TiPaintView.hpp"
-#include "TitaniumWindows/UI/WindowsViewLayoutDelegate.hpp"
-
-namespace Ti
-{
-		using namespace Windows::Devices::Input;
-		using namespace Windows::UI::Core;
-
-		PaintView::PaintView(const JSContext& js_context) TITANIUM_NOEXCEPT
-			: Titanium::UI::View(js_context),
-			strokeWidth__(6),
-			strokeColor__("black"),
-			strokeAlpha__(255),
-			eraseMode__(false),
-			image__("")
-		{
-			TITANIUM_LOG_DEBUG("Ti::Paint::View::ctor Initialize");
-		}
-
-		void PaintView::postCallAsConstructor(const JSContext& js_context, const std::vector& arguments)
-		{
-			Titanium::UI::View::postCallAsConstructor(js_context, arguments);
-
-			canvas__ = ref new Windows::UI::Xaml::Controls::Canvas();
-			canvas__->Background = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::Transparent);
-
-			inputId__ = 0;
-			strokeBrush__ = ref new Windows::UI::Xaml::Media::SolidColorBrush(TitaniumWindows::UI::WindowsViewLayoutDelegate::ColorForName(strokeColor__));
-
-			canvas__->PointerPressed += ref new Windows::UI::Xaml::Input::PointerEventHandler(
-				[=](Platform::Object ^sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) {
-				const auto p = e->GetCurrentPoint(canvas__);
-				inputStart__ = p->Position;
-
-				const auto type = e->Pointer->PointerDeviceType;
-				if (type == PointerDeviceType::Touch || type == PointerDeviceType::Pen || type == PointerDeviceType::Mouse && p->Properties->IsLeftButtonPressed) {
-					inputId__ = p->PointerId;
-					e->Handled = true;
-				}
-			}
-			);
-			canvas__->PointerMoved += ref new Windows::UI::Xaml::Input::PointerEventHandler(
-				[=](Platform::Object ^sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) {
-
-				if (e->Pointer->PointerId == inputId__) {
-					const auto p = e->GetCurrentPoint(canvas__);
-
-					inputEnd__ = p->Position;
-
-					if (std::sqrt(std::pow((inputEnd__.X - inputStart__.X), 2) + std::pow((inputEnd__.Y - inputStart__.Y), 2)) > 1.0) {
-						auto line = ref new Windows::UI::Xaml::Shapes::Line();
-						line->X1 = inputEnd__.X;
-						line->Y1 = inputEnd__.Y;
-						line->X2 = inputStart__.X;
-						line->Y2 = inputStart__.Y;
-						line->StrokeThickness = strokeWidth__;
-						line->StrokeStartLineCap = PenLineCap::Round;
-						line->StrokeEndLineCap = PenLineCap::Round;
-						if (get_eraseMode()) {
-							line->Stroke = canvas__->Background;
-						} else {
-							line->Stroke = strokeBrush__;
-						}
-						canvas__->Children->Append(line);
-
-						inputStart__ = inputEnd__;
-					}
-				}
-			}
-			);
-			canvas__->PointerReleased += ref new Windows::UI::Xaml::Input::PointerEventHandler(
-				[=](Platform::Object ^sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) {
-				inputId__ = 0;
-				e->Handled = true;
-			}
-			);
-
-			Titanium::UI::View::setLayoutDelegate();
-
-			layoutDelegate__->set_defaultHeight(Titanium::UI::LAYOUT::FILL);
-			layoutDelegate__->set_defaultWidth(Titanium::UI::LAYOUT::FILL);
-			layoutDelegate__->set_autoLayoutForHeight(Titanium::UI::LAYOUT::FILL);
-			layoutDelegate__->set_autoLayoutForWidth(Titanium::UI::LAYOUT::FILL);
-
-			getViewLayoutDelegate()->setComponent(canvas__, nullptr, false);
-		}
-
-		void PaintView::JSExportInitialize()
-		{
-			JSExport::SetClassVersion(1);
-			JSExport::SetParent(JSExport::Class());
-
-			TITANIUM_ADD_PROPERTY(PaintView, strokeWidth);
-			TITANIUM_ADD_PROPERTY(PaintView, strokeColor);
-			TITANIUM_ADD_PROPERTY(PaintView, strokeAlpha);
-			TITANIUM_ADD_PROPERTY(PaintView, eraseMode);
-			TITANIUM_ADD_PROPERTY(PaintView, image);
-
-			TITANIUM_ADD_FUNCTION(PaintView, clear);
-		}
-
-		TITANIUM_PROPERTY_READWRITE(PaintView, double, strokeWidth);
-
-		TITANIUM_PROPERTY_GETTER(PaintView, strokeWidth)
-		{
-			return get_context().CreateNumber(get_strokeWidth());
-		}
-
-		TITANIUM_PROPERTY_SETTER(PaintView, strokeWidth)
-		{
-			TITANIUM_ASSERT(argument.IsNumber());
-			set_strokeWidth(static_cast(argument));
-			return true;
-		}
-
-		TITANIUM_PROPERTY_READ(PaintView, std::string, strokeColor);
-
-		TITANIUM_PROPERTY_GETTER(PaintView, strokeColor)
-		{
-			return get_context().CreateString(get_strokeColor());
-		}
-
-		TITANIUM_PROPERTY_SETTER(PaintView, strokeColor)
-		{
-			TITANIUM_ASSERT(argument.IsString());
-			set_strokeColor(static_cast(argument));
-			return true;
-		}
-
-		void PaintView::set_strokeColor(const std::string& color) TITANIUM_NOEXCEPT
-		{
-			strokeColor__ = color;
-			auto brushColor = TitaniumWindows::UI::WindowsViewLayoutDelegate::ColorForName(strokeColor__);
-			brushColor.A = static_cast(strokeAlpha__);
-			strokeBrush__ = ref new Windows::UI::Xaml::Media::SolidColorBrush(brushColor);
-		}
-
-		TITANIUM_PROPERTY_READ(PaintView, int, strokeAlpha);
-
-		TITANIUM_PROPERTY_GETTER(PaintView, strokeAlpha)
-		{
-			return get_context().CreateNumber(get_strokeAlpha());
-		}
-
-		TITANIUM_PROPERTY_SETTER(PaintView, strokeAlpha)
-		{
-			TITANIUM_ASSERT(argument.IsNumber());
-			set_strokeAlpha(static_cast(argument));
-			return true;
-		}
-
-		void PaintView::set_strokeAlpha(const int& alpha) TITANIUM_NOEXCEPT
-		{
-			strokeAlpha__ = alpha;
-			set_strokeColor(strokeColor__);
-		}
-
-		TITANIUM_PROPERTY_READWRITE(PaintView, bool, eraseMode);
-
-		TITANIUM_PROPERTY_GETTER(PaintView, eraseMode)
-		{
-			return get_context().CreateBoolean(get_eraseMode());
-		}
-
-		TITANIUM_PROPERTY_SETTER(PaintView, eraseMode)
-		{
-			TITANIUM_ASSERT(argument.IsBoolean());
-			set_eraseMode(static_cast(argument));
-			return true;
-		}
-
-		TITANIUM_PROPERTY_READWRITE(PaintView, std::string, image);
-
-		TITANIUM_PROPERTY_GETTER(PaintView, image)
-		{
-			return get_context().CreateString(get_image());
-		}
-
-		TITANIUM_PROPERTY_SETTER(PaintView, image)
-		{
-			TITANIUM_ASSERT(argument.IsString());
-			set_image(static_cast(argument));
-			layoutDelegate__->set_backgroundImage(get_image());
-			return true;
-		}
-
-		TITANIUM_FUNCTION(PaintView, clear)
-		{
-			canvas__->Children->Clear();
-			return get_context().CreateUndefined();
-		}
-}
diff --git a/windows/test/CMakeLists.txt b/windows/test/CMakeLists.txt
deleted file mode 100644
index d75de47..0000000
--- a/windows/test/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-# Titanium Windows Native Module - ti.paint
-#
-# Copyright (c) 2015 by Appcelerator, Inc. All Rights Reserved.
-# Licensed under the terms of the Apache Public License.
-# Please see the LICENSE included with this distribution for details.
-
-#cxx_test(ti.paintTests . ti.paint)
\ No newline at end of file
diff --git a/windows/timodule.xml b/windows/timodule.xml
deleted file mode 100644
index 773afc2..0000000
--- a/windows/timodule.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-	
-	
-

From cd5cb4c62543b50e45ec8193a2fbb27bafa78df5 Mon Sep 17 00:00:00 2001
From: m1ga 
Date: Wed, 11 Mar 2026 21:59:09 +0100
Subject: [PATCH 2/3] lint files

---
 ios/Classes/TiPaintModule.h         |  3 +--
 ios/Classes/TiPaintModule.m         | 23 ++++++++++-------------
 ios/Classes/TiPaintModuleAssets.h   |  5 ++---
 ios/Classes/TiPaintModuleAssets.m   | 10 +++-------
 ios/Classes/TiPaintPaintView.h      |  6 +++---
 ios/Classes/TiPaintPaintViewProxy.h |  2 +-
 ios/Classes/WetPaintView.m          | 16 ++++++++--------
 ios/package.json                    | 21 +++++++++++++++++++++
 8 files changed, 49 insertions(+), 37 deletions(-)
 create mode 100644 ios/package.json

diff --git a/ios/Classes/TiPaintModule.h b/ios/Classes/TiPaintModule.h
index e4c72d3..f6fed99 100644
--- a/ios/Classes/TiPaintModule.h
+++ b/ios/Classes/TiPaintModule.h
@@ -6,8 +6,7 @@
 
 #import "TiModule.h"
 
-@interface TiPaintModule : TiModule 
-{
+@interface TiPaintModule : TiModule {
 }
 
 @end
diff --git a/ios/Classes/TiPaintModule.m b/ios/Classes/TiPaintModule.m
index 958ec00..21c0d52 100644
--- a/ios/Classes/TiPaintModule.m
+++ b/ios/Classes/TiPaintModule.m
@@ -14,26 +14,23 @@ @implementation TiPaintModule
 #pragma mark Internal
 
 // this is generated for your module, please do not change it
--(id)moduleGUID
-{
-	return @"43f13063-d426-4e9c-8a7a-72dc5e4aec57";
+- (id)moduleGUID {
+  return @"43f13063-d426-4e9c-8a7a-72dc5e4aec57";
 }
 
 // this is generated for your module, please do not change it
--(NSString*)moduleId
-{
-	return @"ti.paint";
+- (NSString *)moduleId {
+  return @"ti.paint";
 }
 
 #pragma mark Lifecycle
 
--(void)startup
-{
-	// this method is called when the module is first loaded
-	// you *must* call the superclass
-	[super startup];
-	
-	NSLog(@"[DEBUG] %@ loaded",self);
+- (void)startup {
+  // this method is called when the module is first loaded
+  // you *must* call the superclass
+  [super startup];
+
+  NSLog(@"[DEBUG] %@ loaded", self);
 }
 
 @end
diff --git a/ios/Classes/TiPaintModuleAssets.h b/ios/Classes/TiPaintModuleAssets.h
index ee29189..db75bf5 100644
--- a/ios/Classes/TiPaintModuleAssets.h
+++ b/ios/Classes/TiPaintModuleAssets.h
@@ -2,8 +2,7 @@
  * This is a generated file. Do not edit or your changes will be lost
  */
 
-@interface TiPaintModuleAssets : NSObject
-{
+@interface TiPaintModuleAssets : NSObject {
 }
-- (NSData*) moduleAsset;
+- (NSData *)moduleAsset;
 @end
diff --git a/ios/Classes/TiPaintModuleAssets.m b/ios/Classes/TiPaintModuleAssets.m
index 1eff14a..c2af4fa 100644
--- a/ios/Classes/TiPaintModuleAssets.m
+++ b/ios/Classes/TiPaintModuleAssets.m
@@ -3,20 +3,16 @@
  */
 #import "TiPaintModuleAssets.h"
 
-extern NSData* filterDataInRange(NSData* thedata, NSRange range);
+extern NSData *filterDataInRange(NSData *thedata, NSRange range);
 
 @implementation TiPaintModuleAssets
 
-- (NSData *)moduleAsset
-{
-  
+- (NSData *)moduleAsset {
 
   return nil;
 }
 
-- (NSData *)resolveModuleAsset:(NSString *)path
-{
-  
+- (NSData *)resolveModuleAsset:(NSString *)path {
 
   return nil;
 }
diff --git a/ios/Classes/TiPaintPaintView.h b/ios/Classes/TiPaintPaintView.h
index b89b021..892a7cd 100644
--- a/ios/Classes/TiPaintPaintView.h
+++ b/ios/Classes/TiPaintPaintView.h
@@ -9,9 +9,9 @@
 
 @interface TiPaintPaintView : TiUIView  {
 @private
-	UIImageView *drawImage;
-	WetPaintView *wetPaintView;
-	CGRect drawBox;
+  UIImageView *drawImage;
+  WetPaintView *wetPaintView;
+  CGRect drawBox;
 }
 
 @end
diff --git a/ios/Classes/TiPaintPaintViewProxy.h b/ios/Classes/TiPaintPaintViewProxy.h
index b76a399..9fb8a3c 100644
--- a/ios/Classes/TiPaintPaintViewProxy.h
+++ b/ios/Classes/TiPaintPaintViewProxy.h
@@ -12,4 +12,4 @@
 
 }
 
-@end
+  @end
diff --git a/ios/Classes/WetPaintView.m b/ios/Classes/WetPaintView.m
index 5957c4b..cee8229 100644
--- a/ios/Classes/WetPaintView.m
+++ b/ios/Classes/WetPaintView.m
@@ -1,10 +1,10 @@
 /**
  * WetPaintView.m
  * paint
- * 
+ *
  * Created by Dawson Toth on 4/20/12.
  * Copyright (c) 2012 Toth Solutions, LLC. All rights reserved.
- * 
+ *
  * Ti.Paint Module
  * Copyright (c) 2010-2013 by Appcelerator, Inc. All Rights Reserved.
  * Please see the LICENSE included with this distribution for details.
@@ -494,12 +494,12 @@ - (UIColor *)colorFromHexString:(NSString *)hexString {
 
 #pragma mark - UIGestureRecognizerDelegate
 
-- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
-{
-    if ([gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
-        return NO;
-    }
-    return YES;
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
+  if ([gestureRecognizer
+          isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
+    return NO;
+  }
+  return YES;
 }
 
 @end
diff --git a/ios/package.json b/ios/package.json
new file mode 100644
index 0000000..fbd8fc3
--- /dev/null
+++ b/ios/package.json
@@ -0,0 +1,21 @@
+{
+  "name": "ti.paint",
+  "description": "ti.paint",
+  "type": "module",
+  "version": "1.0.0",
+  "author": "TiDev, Inc. ",
+  "scripts": {
+    "format": "npm run lint -- --fix",
+    "lint": "clang-format-lint $npm_package_config_format_objc"
+  },
+  "config": {
+    "format": {
+      "objc": "Classes/*.{m,h}"
+    }
+  },
+  "devDependencies": {
+    "@seadub/clang-format-lint": "0.0.2",
+    "clang-format": "^1.8.0"
+  },
+  "license": "Apache-2.0"
+}

From 7112c46c0b03be575d5812cff3a236c756a9a45e Mon Sep 17 00:00:00 2001
From: m1ga 
Date: Thu, 9 Jul 2026 13:58:32 +0200
Subject: [PATCH 3/3] resize parity on rotation change

---
 ios/Classes/TiPaintPaintView.m | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/ios/Classes/TiPaintPaintView.m b/ios/Classes/TiPaintPaintView.m
index 73e267d..56ba37e 100644
--- a/ios/Classes/TiPaintPaintView.m
+++ b/ios/Classes/TiPaintPaintView.m
@@ -39,14 +39,26 @@ - (void)dealloc {
 - (void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds {
   [super frameSizeChanged:frame bounds:bounds];
   [wetPaintView setFrame:bounds];
+
+  CGRect newDrawBox = CGRectMake(bounds.origin.x, bounds.origin.y,
+                                 ceilf(bounds.size.width), ceilf(bounds.size.height));
+
   if (drawImage != nil) {
+    // Re-render backing image at the new size to avoid stretching
+    if (!CGSizeEqualToSize(drawBox.size, newDrawBox.size) && drawImage.image != nil) {
+      UIGraphicsBeginImageContextWithOptions(newDrawBox.size, NO, 0.0);
+      [drawImage.image drawInRect:CGRectMake(0, 0, newDrawBox.size.width, newDrawBox.size.height)];
+      drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
+      UIGraphicsEndImageContext();
+    }
+
     [drawImage setFrame:bounds];
   }
 
-  // MOD-348: Ensure that we get a solid box in which to draw. Otherwise, we'll
-  // end up with blurry lines and visual defects.
-  drawBox = CGRectMake(bounds.origin.x, bounds.origin.y,
-                       ceilf(bounds.size.width), ceilf(bounds.size.height));
+  drawBox = newDrawBox;
+
+  // Force redraw of wet paint strokes so they appear after resize
+  [wetPaintView setNeedsDisplay];
 }
 
 #pragma mark Utility