mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Drawing improvements and fixes
This commit is contained in:
parent
f4f446a708
commit
20a381c595
@ -5521,3 +5521,8 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Conversation.Timer.Title" = "Send With Timer";
|
||||
"Conversation.Timer.Send" = "Send With Timer";
|
||||
|
||||
"Paint.Pen" = "Pen";
|
||||
"Paint.Marker" = "Marker";
|
||||
"Paint.Neon" = "Neon";
|
||||
"Paint.Arrow" = "Arrow";
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_font.pdf",
|
||||
"filename" : "ic_menu_brush4.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushArrow.imageset/ic_menu_brush4.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushArrow.imageset/ic_menu_brush4.pdf
vendored
Normal file
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushMarker.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushMarker.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_brush2.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushMarker.imageset/ic_menu_brush2.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushMarker.imageset/ic_menu_brush2.pdf
vendored
Normal file
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushNeon.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushNeon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_brush3.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushNeon.imageset/ic_menu_brush3.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushNeon.imageset/ic_menu_brush3.pdf
vendored
Normal file
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushPen.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushPen.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_brush1.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushPen.imageset/ic_menu_brush1.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushPen.imageset/ic_menu_brush1.pdf
vendored
Normal file
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_brush4.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_brush2.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_brush3.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushSelectedPen.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushSelectedPen.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_brush1.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextFramed.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextFramed.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_font3.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextFramed.imageset/ic_menu_font3.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextFramed.imageset/ic_menu_font3.pdf
vendored
Normal file
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextOutlined.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextOutlined.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_font2.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextOutlined.imageset/ic_menu_font2.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextOutlined.imageset/ic_menu_font2.pdf
vendored
Normal file
Binary file not shown.
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextRegular.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextRegular.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_menu_font1.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextRegular.imageset/ic_menu_font1.pdf
vendored
Normal file
BIN
submodules/LegacyComponents/LegacyImages.xcassets/Editor/TextRegular.imageset/ic_menu_font1.pdf
vendored
Normal file
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_font3.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_font2.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_editor_font1.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -3,13 +3,18 @@
|
||||
#import <LegacyComponents/TGMediaSelectionContext.h>
|
||||
|
||||
@class AVURLAsset;
|
||||
@class TGMediaAsset;
|
||||
|
||||
@interface TGCameraCapturedVideo : NSObject <TGMediaEditableItem, TGMediaSelectableItem>
|
||||
|
||||
@property (nonatomic, readonly) AVURLAsset *avAsset;
|
||||
@property (nonatomic, readonly) SSignal *avAsset;
|
||||
@property (nonatomic, readonly) NSTimeInterval videoDuration;
|
||||
@property (nonatomic, readonly) bool isAnimation;
|
||||
@property (nonatomic, readonly) TGMediaAsset *originalAsset;
|
||||
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)url;
|
||||
- (instancetype)initWithAsset:(TGMediaAsset *)asset;
|
||||
|
||||
- (void)_cleanUp;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
@interface TGMediaPickerGalleryVideoItem : TGMediaPickerGalleryItem <TGModernGallerySelectableItem, TGModernGalleryEditableItem>
|
||||
|
||||
@property (nonatomic, readonly) AVAsset *avAsset;
|
||||
@property (nonatomic, readonly) SSignal *avAsset;
|
||||
@property (nonatomic, readonly) CGSize dimensions;
|
||||
- (SSignal *)durationSignal;
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
@interface TGMediaSelectionChange : NSObject
|
||||
|
||||
@property (nonatomic, readonly) id<TGMediaSelectableItem> item;
|
||||
@property (nonatomic, readonly) NSObject <TGMediaSelectableItem> *item;
|
||||
@property (nonatomic, readonly) bool selected;
|
||||
@property (nonatomic, readonly) bool animated;
|
||||
@property (nonatomic, readonly, strong) id sender;
|
||||
|
@ -4,6 +4,12 @@
|
||||
@class TGPhotoPaintEntitySelectionView;
|
||||
@class TGPaintUndoManager;
|
||||
|
||||
@interface UIView (PixelColor)
|
||||
|
||||
- (UIColor *)colorAtPoint:(CGPoint)point;
|
||||
|
||||
@end
|
||||
|
||||
@interface TGPhotoPaintEntityView : UIView
|
||||
{
|
||||
NSInteger _entityUUID;
|
||||
@ -55,4 +61,4 @@
|
||||
- (void)fadeIn;
|
||||
- (void)fadeOut;
|
||||
|
||||
@end
|
||||
@end
|
||||
|
@ -4,9 +4,9 @@
|
||||
@class TGPhotoPaintFont;
|
||||
|
||||
typedef enum {
|
||||
TGPhotoPaintTextEntityStyleBorder,
|
||||
TGPhotoPaintTextEntityStyleClassic,
|
||||
TGPhotoPaintTextEntityStyleFrame
|
||||
TGPhotoPaintTextEntityStyleOutlined,
|
||||
TGPhotoPaintTextEntityStyleRegular,
|
||||
TGPhotoPaintTextEntityStyleFramed
|
||||
} TGPhotoPaintTextEntityStyle;
|
||||
|
||||
@interface TGPhotoPaintTextEntity : TGPhotoPaintEntity
|
||||
|
@ -270,13 +270,21 @@
|
||||
|
||||
GPUImageOutput *currentInput = _currentInput;
|
||||
if ([currentInput isKindOfClass:[PGVideoMovie class]]) {
|
||||
if (!_playing) {
|
||||
_playing = true;
|
||||
[_videoQueue dispatch:^{
|
||||
if ([currentInput isKindOfClass:[PGVideoMovie class]]) {
|
||||
[(PGVideoMovie *)currentInput startProcessing];
|
||||
}
|
||||
}];
|
||||
if (capture) {
|
||||
if ([currentInput isKindOfClass:[PGVideoMovie class]])
|
||||
[(PGVideoMovie *)currentInput process];
|
||||
[_finalFilter useNextFrameForImageCapture];
|
||||
if (completion != nil)
|
||||
completion();
|
||||
} else {
|
||||
if (!_playing) {
|
||||
_playing = true;
|
||||
[_videoQueue dispatch:^{
|
||||
if ([currentInput isKindOfClass:[PGVideoMovie class]]) {
|
||||
[(PGVideoMovie *)currentInput startProcessing];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
} else if ([currentInput isKindOfClass:[GPUImageTextureInput class]]) {
|
||||
if (capture)
|
||||
|
@ -14,6 +14,7 @@
|
||||
- (void)cancelProcessing;
|
||||
- (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer;
|
||||
|
||||
- (void)process;
|
||||
- (void)reprocessCurrent;
|
||||
|
||||
@end
|
||||
|
@ -250,6 +250,11 @@ NSString *const kYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRIN
|
||||
[self processPixelBufferAtTime:outputItemTime];
|
||||
}
|
||||
|
||||
- (void)process {
|
||||
_shouldReprocessCurrentFrame = true;
|
||||
[self displayLinkCallback:displayLink];
|
||||
}
|
||||
|
||||
- (void)processPixelBufferAtTime:(CMTime)outputItemTime
|
||||
{
|
||||
if ([playerItemOutput hasNewPixelBufferForItemTime:outputItemTime] || _shouldReprocessCurrentFrame)
|
||||
|
@ -178,7 +178,13 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
NSInteger index = [strongSelf->_fetchResult indexOfAsset:(TGMediaAsset *)change.item];
|
||||
NSInteger index = 0;
|
||||
if ([change.item isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
index = [strongSelf->_fetchResult indexOfAsset:((TGCameraCapturedVideo *)change.item).originalAsset];
|
||||
} else {
|
||||
index = [strongSelf->_fetchResult indexOfAsset:(TGMediaAsset *)change.item];
|
||||
}
|
||||
|
||||
[strongSelf updateSendButtonsFromIndex:index];
|
||||
|
||||
[strongSelf updateSelectionIndexes];
|
||||
@ -917,7 +923,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
if ([editableItem isKindOfClass:[TGMediaAsset class]]) {
|
||||
return [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)editableItem];
|
||||
} else if ([editableItem isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
return [SSignal single:((TGCameraCapturedVideo *)editableItem).avAsset];
|
||||
return ((TGCameraCapturedVideo *)editableItem).avAsset;
|
||||
} else {
|
||||
return [editableItem originalImageSignal:position];
|
||||
}
|
||||
|
@ -3,21 +3,49 @@
|
||||
#import <LegacyComponents/TGMediaAssetImageSignals.h>
|
||||
#import <LegacyComponents/TGPhotoEditorUtils.h>
|
||||
|
||||
#import "LegacyComponentsGlobals.h"
|
||||
#import "TGStringUtils.h"
|
||||
#import "TGMediaAsset.h"
|
||||
#import "TGMediaAsset+TGMediaEditableItem.h"
|
||||
|
||||
#import "TGGifConverter.h"
|
||||
|
||||
@interface TGCameraCapturedVideo ()
|
||||
{
|
||||
CGSize _cachedSize;
|
||||
NSTimeInterval _cachedDuration;
|
||||
|
||||
AVURLAsset *_cachedAVAsset;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TGCameraCapturedVideo
|
||||
|
||||
+ (NSURL *)videoURLForAsset:(TGMediaAsset *)asset {
|
||||
NSURL *convertedGifsUrl = [NSURL fileURLWithPath:[[[LegacyComponentsGlobals provider] dataStoragePath] stringByAppendingPathComponent:@"convertedGifs"]];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:convertedGifsUrl.path withIntermediateDirectories:true attributes:nil error:nil];
|
||||
return [convertedGifsUrl URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4", [TGStringUtils md5:asset.identifier]]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)url
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_avAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
|
||||
_cachedAVAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
|
||||
_cachedSize = CGSizeZero;
|
||||
_cachedDuration = 0.0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithAsset:(TGMediaAsset *)asset
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
_originalAsset = asset;
|
||||
|
||||
_cachedSize = CGSizeZero;
|
||||
_cachedDuration = 0.0;
|
||||
}
|
||||
@ -26,7 +54,9 @@
|
||||
|
||||
- (void)_cleanUp
|
||||
{
|
||||
[[NSFileManager defaultManager] removeItemAtPath:_avAsset.URL.path error:nil];
|
||||
if (_originalAsset == nil) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:_cachedAVAsset.URL.path error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)isVideo
|
||||
@ -34,9 +64,47 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- (bool)isAnimation {
|
||||
return _originalAsset != nil;
|
||||
}
|
||||
|
||||
- (SSignal *)avAsset {
|
||||
if (_originalAsset != nil) {
|
||||
if (_cachedAVAsset != nil) {
|
||||
return [SSignal single:_cachedAVAsset];
|
||||
} else {
|
||||
NSURL *videoUrl = [TGCameraCapturedVideo videoURLForAsset:_originalAsset];
|
||||
return [[TGMediaAssetImageSignals imageDataForAsset:_originalAsset allowNetworkAccess:false] mapToSignal:^SSignal *(TGMediaAssetImageData *assetData) {
|
||||
NSData *data = assetData.imageData;
|
||||
|
||||
const char *gif87Header = "GIF87";
|
||||
const char *gif89Header = "GIF89";
|
||||
if (data.length >= 5 && (!memcmp(data.bytes, gif87Header, 5) || !memcmp(data.bytes, gif89Header, 5)))
|
||||
{
|
||||
return [[TGGifConverter convertGifToMp4:data] map:^id(NSDictionary *result)
|
||||
{
|
||||
NSString *filePath = result[@"path"];
|
||||
[[NSFileManager defaultManager] moveItemAtPath:filePath toPath:videoUrl.path error:nil];
|
||||
|
||||
return [AVURLAsset assetWithURL:videoUrl];
|
||||
}];
|
||||
} else {
|
||||
return [SSignal complete];
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
return [SSignal single:_cachedAVAsset];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)uniqueIdentifier
|
||||
{
|
||||
return _avAsset.URL.absoluteString;
|
||||
if (_originalAsset) {
|
||||
return _originalAsset.uniqueIdentifier;
|
||||
} else {
|
||||
return _cachedAVAsset.URL.absoluteString;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)originalSize
|
||||
@ -44,7 +112,11 @@
|
||||
if (!CGSizeEqualToSize(_cachedSize, CGSizeZero))
|
||||
return _cachedSize;
|
||||
|
||||
AVAssetTrack *track = _avAsset.tracks.firstObject;
|
||||
if (_originalAsset != nil) {
|
||||
return [_originalAsset originalSize];
|
||||
}
|
||||
|
||||
AVAssetTrack *track = _cachedAVAsset.tracks.firstObject;
|
||||
_cachedSize = CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size;
|
||||
return _cachedSize;
|
||||
}
|
||||
@ -59,29 +131,41 @@
|
||||
if (_cachedDuration > DBL_EPSILON)
|
||||
return _cachedDuration;
|
||||
|
||||
_cachedDuration = CMTimeGetSeconds(_avAsset.duration);
|
||||
if (_cachedAVAsset != nil) {
|
||||
_cachedDuration = CMTimeGetSeconds(_cachedAVAsset.duration);
|
||||
}
|
||||
return _cachedDuration;
|
||||
}
|
||||
|
||||
- (SSignal *)thumbnailImageSignal
|
||||
{
|
||||
CGFloat thumbnailImageSide = TGPhotoEditorScreenImageMaxSize().width;
|
||||
CGSize size = TGScaleToSize(self.originalSize, CGSizeMake(thumbnailImageSide, thumbnailImageSide));
|
||||
if (_originalAsset != nil) {
|
||||
return [_originalAsset thumbnailImageSignal];
|
||||
} else {
|
||||
CGFloat thumbnailImageSide = TGPhotoEditorScreenImageMaxSize().width;
|
||||
CGSize size = TGScaleToSize(self.originalSize, CGSizeMake(thumbnailImageSide, thumbnailImageSide));
|
||||
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:_avAsset size:size timestamp:kCMTimeZero];
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:_cachedAVAsset size:size timestamp:kCMTimeZero];
|
||||
}
|
||||
}
|
||||
|
||||
- (SSignal *)screenImageSignal:(NSTimeInterval)__unused position
|
||||
- (SSignal *)screenImageSignal:(NSTimeInterval)position
|
||||
{
|
||||
CGFloat imageSide = 1280.0f;
|
||||
CGSize size = TGScaleToSize(self.originalSize, CGSizeMake(imageSide, imageSide));
|
||||
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:_avAsset size:size timestamp:kCMTimeZero];
|
||||
if (_originalAsset != nil) {
|
||||
return [_originalAsset screenImageSignal:position];
|
||||
} else {
|
||||
CGFloat imageSide = 1280.0f;
|
||||
CGSize size = TGScaleToSize(self.originalSize, CGSizeMake(imageSide, imageSide));
|
||||
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:_cachedAVAsset size:size timestamp:kCMTimeZero];
|
||||
}
|
||||
}
|
||||
|
||||
- (SSignal *)originalImageSignal:(NSTimeInterval)position
|
||||
{
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:_avAsset size:self.originalSize timestamp:CMTimeMakeWithSeconds(position, NSEC_PER_SEC)];
|
||||
return [[self avAsset] mapToSignal:^SSignal *(AVURLAsset *avAsset) {
|
||||
return [TGMediaAssetImageSignals videoThumbnailForAVAsset:avAsset size:self.originalSize timestamp:CMTimeMakeWithSeconds(position, NSEC_PER_SEC)];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1772,7 +1772,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
if ([editableItem isKindOfClass:[TGMediaAsset class]]) {
|
||||
return [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)editableItem];
|
||||
} else if ([editableItem isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
return [SSignal single:((TGCameraCapturedVideo *)editableItem).avAsset];
|
||||
return ((TGCameraCapturedVideo *)editableItem).avAsset;
|
||||
} else {
|
||||
return [editableItem originalImageSignal:position];
|
||||
}
|
||||
@ -2467,7 +2467,9 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
else if ([item isKindOfClass:[TGCameraCapturedVideo class]])
|
||||
{
|
||||
TGCameraCapturedVideo *video = (TGCameraCapturedVideo *)item;
|
||||
return [SSignal single:@{@"type": @"video", @"url": video.avAsset.URL}];
|
||||
return [[video avAsset] mapToSignal:^SSignal *(AVURLAsset *avAsset) {
|
||||
return [SSignal single:@{@"type": @"video", @"url": avAsset.URL}];
|
||||
}];
|
||||
}
|
||||
|
||||
return [SSignal complete];
|
||||
@ -2689,9 +2691,11 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
};
|
||||
|
||||
CGSize imageSize = TGFillSize(asset.originalSize, CGSizeMake(512, 512));
|
||||
SSignal *trimmedVideoThumbnailSignal = [[TGMediaAssetImageSignals videoThumbnailForAVAsset:video.avAsset size:imageSize timestamp:CMTimeMakeWithSeconds(adjustments.trimStartValue, NSEC_PER_SEC)] map:^UIImage *(UIImage *image)
|
||||
{
|
||||
SSignal *trimmedVideoThumbnailSignal = [[video avAsset] mapToSignal:^SSignal *(AVURLAsset *avAsset) {
|
||||
return [[TGMediaAssetImageSignals videoThumbnailForAVAsset:avAsset size:imageSize timestamp:CMTimeMakeWithSeconds(adjustments.trimStartValue, NSEC_PER_SEC)] map:^UIImage *(UIImage *image)
|
||||
{
|
||||
return cropVideoThumbnail(image, TGScaleToFill(asset.originalSize, CGSizeMake(512, 512)), asset.originalSize, true);
|
||||
}];
|
||||
}];
|
||||
|
||||
SSignal *videoThumbnailSignal = [inlineThumbnailSignal(asset) map:^UIImage *(UIImage *image)
|
||||
@ -2709,7 +2713,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
{
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
dict[@"type"] = @"cameraVideo";
|
||||
dict[@"url"] = video.avAsset.URL;
|
||||
// dict[@"url"] = video.avAsset.URL;
|
||||
dict[@"previewImage"] = image;
|
||||
dict[@"adjustments"] = adjustments;
|
||||
dict[@"dimensions"] = [NSValue valueWithCGSize:dimensions];
|
||||
|
@ -1026,7 +1026,7 @@
|
||||
if ([editableItem isKindOfClass:[TGMediaAsset class]]) {
|
||||
return [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)editableItem];
|
||||
} else if ([editableItem isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
return [SSignal single:((TGCameraCapturedVideo *)editableItem).avAsset];
|
||||
return ((TGCameraCapturedVideo *)editableItem).avAsset;
|
||||
} else {
|
||||
return [editableItem originalImageSignal:position];
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
- (TGPhotoEditorTab)toolbarTabs
|
||||
{
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorToolsTab | TGPhotoEditorPaintTab | TGPhotoEditorTimerTab;
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorToolsTab | TGPhotoEditorPaintTab;
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,7 +77,11 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize targetSize = TGFitSizeF(CGSizeMake(sourceWidth, sourceHeight), CGSizeMake(TGGifConverterMaximumSide, TGGifConverterMaximumSide));
|
||||
const CGFloat blockSize = 16.0f;
|
||||
CGFloat renderWidth = CGFloor(sourceWidth / blockSize) * blockSize;
|
||||
CGFloat renderHeight = CGFloor(sourceHeight * renderWidth / sourceWidth);
|
||||
|
||||
CGSize targetSize = TGFitSizeF(CGSizeMake(renderWidth, renderHeight), CGSizeMake(TGGifConverterMaximumSide, TGGifConverterMaximumSide));
|
||||
|
||||
NSDictionary *videoCleanApertureSettings = @
|
||||
{
|
||||
@ -122,8 +126,8 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
NSDictionary *attributes = @
|
||||
{
|
||||
(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32ARGB),
|
||||
(NSString *)kCVPixelBufferWidthKey : @(sourceWidth),
|
||||
(NSString *)kCVPixelBufferHeightKey : @(sourceHeight),
|
||||
(NSString *)kCVPixelBufferWidthKey : @(renderWidth),
|
||||
(NSString *)kCVPixelBufferHeightKey : @(renderHeight),
|
||||
(NSString *)kCVPixelBufferCGImageCompatibilityKey : @YES,
|
||||
(NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES
|
||||
};
|
||||
@ -148,7 +152,7 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
|
||||
if (gifProperties != NULL)
|
||||
{
|
||||
CVPixelBufferRef pxBuffer = [self newBufferFrom:imgRef withPixelBufferPool:adaptor.pixelBufferPool andAttributes:adaptor.sourcePixelBufferAttributes];
|
||||
CVPixelBufferRef pxBuffer = [self newBufferFrom:imgRef size:targetSize withPixelBufferPool:adaptor.pixelBufferPool andAttributes:adaptor.sourcePixelBufferAttributes];
|
||||
if (pxBuffer != NULL)
|
||||
{
|
||||
if (previewImage == nil) {
|
||||
@ -231,13 +235,10 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
}];
|
||||
};
|
||||
|
||||
+ (CVPixelBufferRef)newBufferFrom:(CGImageRef)frame withPixelBufferPool:(CVPixelBufferPoolRef)pixelBufferPool andAttributes:(NSDictionary *)attributes
|
||||
+ (CVPixelBufferRef)newBufferFrom:(CGImageRef)frame size:(CGSize)size withPixelBufferPool:(CVPixelBufferPoolRef)pixelBufferPool andAttributes:(NSDictionary *)attributes
|
||||
{
|
||||
NSParameterAssert(frame);
|
||||
|
||||
size_t width = CGImageGetWidth(frame);
|
||||
size_t height = CGImageGetHeight(frame);
|
||||
size_t bpc = 8;
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
CVPixelBufferRef pxBuffer = NULL;
|
||||
@ -246,7 +247,7 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
if (pixelBufferPool)
|
||||
status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferPool, &pxBuffer);
|
||||
else
|
||||
status = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)attributes, &pxBuffer);
|
||||
status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)attributes, &pxBuffer);
|
||||
|
||||
NSAssert(status == kCVReturnSuccess, @"Could not create a pixel buffer");
|
||||
|
||||
@ -255,10 +256,10 @@ const CGFloat TGGifConverterMaximumSide = 720.0f;
|
||||
|
||||
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pxBuffer);
|
||||
|
||||
CGContextRef context = CGBitmapContextCreate(pxData, width, height, bpc, bytesPerRow, colorSpace, kCGImageAlphaNoneSkipFirst);
|
||||
CGContextRef context = CGBitmapContextCreate(pxData, size.width, size.height, 8, bytesPerRow, colorSpace, kCGImageAlphaNoneSkipFirst);
|
||||
NSAssert(context, @"Could not create a context");
|
||||
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, width, height), frame);
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), frame);
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(pxBuffer, 0);
|
||||
|
||||
|
@ -434,7 +434,7 @@
|
||||
if ([editableItem isKindOfClass:[TGMediaAsset class]]) {
|
||||
return [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)editableItem];
|
||||
} else if ([editableItem isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
return [SSignal single:((TGCameraCapturedVideo *)editableItem).avAsset];
|
||||
return ((TGCameraCapturedVideo *)editableItem).avAsset;
|
||||
} else {
|
||||
return [editableItem originalImageSignal:position];
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#import "TGModernGallerySelectableItem.h"
|
||||
#import "TGModernGalleryEditableItem.h"
|
||||
#import "TGMediaPickerGalleryPhotoItem.h"
|
||||
#import "TGMediaPickerGalleryVideoItem.h"
|
||||
#import "TGMediaPickerGalleryPhotoItemView.h"
|
||||
#import "TGMediaPickerGalleryVideoItemView.h"
|
||||
|
||||
@ -571,7 +572,15 @@
|
||||
[strongSelf->_portraitToolbarView setEditButtonsEnabled:available animated:true];
|
||||
[strongSelf->_landscapeToolbarView setEditButtonsEnabled:available animated:true];
|
||||
|
||||
|
||||
|
||||
bool sendableAsGif = !strongSelf->_inhibitMute && [strongItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]];
|
||||
if ([strongSelf->_currentItem isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) {
|
||||
TGMediaPickerGalleryVideoItem *item = (TGMediaPickerGalleryVideoItem *)strongSelf->_currentItem;
|
||||
if ([item.asset isKindOfClass:[TGCameraCapturedVideo class]] && ((TGCameraCapturedVideo *)item.asset).isAnimation) {
|
||||
sendableAsGif = false;
|
||||
}
|
||||
}
|
||||
strongSelf->_muteButton.hidden = !sendableAsGif;
|
||||
}
|
||||
}]];
|
||||
|
@ -575,7 +575,7 @@
|
||||
if ([editableItem isKindOfClass:[TGMediaAsset class]]) {
|
||||
return [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)editableItem];
|
||||
} else if ([editableItem isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
return [SSignal single:((TGCameraCapturedVideo *)editableItem).avAsset];
|
||||
return ((TGCameraCapturedVideo *)editableItem).avAsset;
|
||||
} else {
|
||||
return [editableItem originalImageSignal:position];
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#import "TGMediaPickerGalleryPhotoItemView.h"
|
||||
|
||||
#import <PhotosUI/PhotosUI.h>
|
||||
|
||||
#import "LegacyComponentsInternal.h"
|
||||
#import "TGFont.h"
|
||||
#import "TGStringUtils.h"
|
||||
@ -34,7 +32,6 @@
|
||||
void (^_currentAvailabilityObserver)(bool);
|
||||
|
||||
UIView *_temporaryRepView;
|
||||
PHLivePhotoView *_livePhotoView;
|
||||
|
||||
UIView *_contentView;
|
||||
UIView *_contentWrapperView;
|
||||
@ -116,11 +113,6 @@
|
||||
{
|
||||
_imageView.hidden = false;
|
||||
[_imageView reset];
|
||||
if (_livePhotoView != nil)
|
||||
{
|
||||
[_livePhotoView removeFromSuperview];
|
||||
_livePhotoView = nil;
|
||||
}
|
||||
[self setProgressVisible:false value:0.0f animated:false];
|
||||
}
|
||||
|
||||
@ -231,8 +223,7 @@
|
||||
}
|
||||
|
||||
[strongSelf reset];
|
||||
|
||||
strongSelf->_livePhotoView.frame = strongSelf->_imageView.frame;
|
||||
|
||||
}]];
|
||||
|
||||
if (!item.asFile)
|
||||
|
@ -50,9 +50,7 @@
|
||||
return;
|
||||
|
||||
if (next.selected)
|
||||
{
|
||||
[strongSelf addSelectedItem:next.item];
|
||||
}
|
||||
else if (!strongSelf->_keepItems)
|
||||
[strongSelf removeSelectedItem:next.item];
|
||||
}]];
|
||||
|
@ -25,7 +25,7 @@
|
||||
return CGSizeZero;
|
||||
}
|
||||
|
||||
- (AVAsset *)avAsset
|
||||
- (SSignal *)avAsset
|
||||
{
|
||||
if ([self.asset isKindOfClass:[TGCameraCapturedVideo class]])
|
||||
return ((TGCameraCapturedVideo *)self.asset).avAsset;
|
||||
@ -70,10 +70,13 @@
|
||||
|
||||
- (TGPhotoEditorTab)toolbarTabs
|
||||
{
|
||||
if ([self.asset isKindOfClass:[TGMediaAsset class]] && ((TGMediaAsset *)self.asset).subtypes & TGMediaAssetSubtypePhotoLive)
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorPaintTab | TGPhotoEditorToolsTab | TGPhotoEditorTimerTab;
|
||||
else
|
||||
if ([self.asset isKindOfClass:[TGMediaAsset class]] && ((TGMediaAsset *)self.asset).subtypes & TGMediaAssetSubtypePhotoLive) {
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorPaintTab | TGPhotoEditorToolsTab;
|
||||
} else if ([self.asset isKindOfClass:[TGCameraCapturedVideo class]] && ((TGCameraCapturedVideo *)self.asset).isAnimation) {
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorPaintTab | TGPhotoEditorToolsTab;
|
||||
} else {
|
||||
return TGPhotoEditorCropTab | TGPhotoEditorToolsTab | TGPhotoEditorPaintTab | TGPhotoEditorQualityTab;
|
||||
}
|
||||
}
|
||||
|
||||
- (Class)viewClass
|
||||
|
@ -1045,16 +1045,16 @@
|
||||
if (_videoView != nil)
|
||||
{
|
||||
SMetaDisposable *currentAudioSession = _currentAudioSession;
|
||||
// if (currentAudioSession)
|
||||
// {
|
||||
if (currentAudioSession)
|
||||
{
|
||||
// _videoView.deallocBlock = ^
|
||||
// {
|
||||
// [[SQueue concurrentDefaultQueue] dispatch:^
|
||||
// {
|
||||
// [currentAudioSession setDisposable:nil];
|
||||
// }];
|
||||
[[SQueue concurrentDefaultQueue] dispatch:^
|
||||
{
|
||||
[currentAudioSession setDisposable:nil];
|
||||
}];
|
||||
// };
|
||||
// }
|
||||
}
|
||||
// [_videoView cleanupPlayer];
|
||||
_photoEditor.previewOutput = nil;
|
||||
|
||||
@ -1092,10 +1092,14 @@
|
||||
[self inhibitVolumeOverlay];
|
||||
|
||||
SSignal *itemSignal = nil;
|
||||
if ([self.item.asset isKindOfClass:[TGMediaAsset class]])
|
||||
if ([self.item.asset isKindOfClass:[TGMediaAsset class]]) {
|
||||
itemSignal = [TGMediaAssetImageSignals playerItemForVideoAsset:(TGMediaAsset *)self.item.asset];
|
||||
else if (self.item.avAsset != nil)
|
||||
itemSignal = [SSignal single:[AVPlayerItem playerItemWithAsset:self.item.avAsset]];
|
||||
}
|
||||
else if (self.item.avAsset != nil) {
|
||||
itemSignal = [self.item.avAsset mapToSignal:^SSignal *(AVAsset *avAsset) {
|
||||
return [SSignal single:[AVPlayerItem playerItemWithAsset:avAsset]];
|
||||
}];
|
||||
}
|
||||
|
||||
[_playerItemDisposable setDisposable:[[itemSignal deliverOn:[SQueue mainQueue]] startWithNext:^(AVPlayerItem *playerItem)
|
||||
{
|
||||
@ -1546,7 +1550,7 @@
|
||||
if (timestamps.count == 0)
|
||||
return;
|
||||
|
||||
AVAsset *avAsset = self.item.avAsset ?: _player.currentItem.asset;
|
||||
SSignal *avAsset = self.item.avAsset ?: [SSignal single:_player.currentItem.asset];
|
||||
TGMediaEditingContext *editingContext = self.item.editingContext;
|
||||
id<TGMediaEditableItem> editableItem = self.item.editableMediaItem;
|
||||
|
||||
@ -1554,7 +1558,9 @@
|
||||
if ([self.item.asset isKindOfClass:[TGMediaAsset class]] && ![self itemIsLivePhoto])
|
||||
thumbnailsSignal = [TGMediaAssetImageSignals videoThumbnailsForAsset:self.item.asset size:size timestamps:timestamps];
|
||||
else if (avAsset != nil)
|
||||
thumbnailsSignal = [TGMediaAssetImageSignals videoThumbnailsForAVAsset:avAsset size:size timestamps:timestamps];
|
||||
thumbnailsSignal = [avAsset mapToSignal:^SSignal *(AVAsset *avAsset) {
|
||||
return [TGMediaAssetImageSignals videoThumbnailsForAVAsset:avAsset size:size timestamps:timestamps];
|
||||
}];
|
||||
|
||||
_requestingThumbnails = true;
|
||||
|
||||
|
@ -370,13 +370,18 @@
|
||||
|
||||
case TGMediaAssetGifType:
|
||||
{
|
||||
// TGCameraCapturedVideo *convertedAsset = [[TGCameraCapturedVideo alloc] initWithAsset:asset];
|
||||
// galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:convertedAsset];
|
||||
galleryItem = [[TGMediaPickerGalleryGifItem alloc] initWithAsset:asset];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
galleryItem = [[TGMediaPickerGalleryPhotoItem alloc] initWithAsset:asset];
|
||||
if (asset.subtypes & TGMediaAssetSubtypePhotoLive)
|
||||
galleryItem = [[TGMediaPickerGalleryVideoItem alloc] initWithAsset:asset];
|
||||
else
|
||||
galleryItem = [[TGMediaPickerGalleryPhotoItem alloc] initWithAsset:asset];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
||||
|
||||
_countLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -0.5f, frame.size.width + 1.0, frame.size.height)];
|
||||
_countLabel.backgroundColor = [UIColor clearColor];
|
||||
_countLabel.font = [TGFont roundedFontOfSize:17];
|
||||
_countLabel.font = [TGFont roundedFontOfSize:18];
|
||||
_countLabel.text = [TGStringUtils stringWithLocalizedNumber:0];
|
||||
_countLabel.textColor = [UIColor whiteColor];
|
||||
[_wrapperView addSubview:_countLabel];
|
||||
@ -299,15 +299,15 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
||||
{
|
||||
labelOrigin = 12 + TGScreenPixel + (38 - labelWidth) / 2;
|
||||
|
||||
if ([_countLabel.text isEqualToString:@"1"] || [_countLabel.text isEqualToString:@"4"])
|
||||
labelOrigin -= 2 * TGScreenPixel;
|
||||
// if ([_countLabel.text isEqualToString:@"1"] || [_countLabel.text isEqualToString:@"4"])
|
||||
// labelOrigin -= 2 * TGScreenPixel;
|
||||
}
|
||||
else
|
||||
{
|
||||
labelOrigin = (processingLabelWidth > 0) ? -processingLabelWidth + 19 + 13 - 4.5f: 64 - 38 + (38 - labelWidth) / 2.0f - 13;
|
||||
}
|
||||
|
||||
_countLabel.frame = CGRectMake(labelOrigin, 6.0f, labelWidth, _countLabel.frame.size.height);
|
||||
_countLabel.frame = CGRectMake(labelOrigin, 5.0 + TGScreenPixel, labelWidth, _countLabel.frame.size.height);
|
||||
_countLabel.transform = transform;
|
||||
}
|
||||
|
||||
|
5
submodules/LegacyComponents/Sources/TGPaintArrowBrush.h
Normal file
5
submodules/LegacyComponents/Sources/TGPaintArrowBrush.h
Normal file
@ -0,0 +1,5 @@
|
||||
#import "TGPaintBrush.h"
|
||||
|
||||
@interface TGPaintArrowBrush : TGPaintBrush
|
||||
|
||||
@end
|
90
submodules/LegacyComponents/Sources/TGPaintArrowBrush.m
Normal file
90
submodules/LegacyComponents/Sources/TGPaintArrowBrush.m
Normal file
@ -0,0 +1,90 @@
|
||||
#import "TGPaintArrowBrush.h"
|
||||
|
||||
const CGFloat TGPaintArrowBrushHardness = 0.92f;
|
||||
|
||||
@implementation TGPaintArrowBrush
|
||||
|
||||
- (CGFloat)spacing
|
||||
{
|
||||
return 0.15f;
|
||||
}
|
||||
|
||||
- (CGFloat)alpha
|
||||
{
|
||||
return 0.85f;
|
||||
}
|
||||
|
||||
- (CGFloat)angle
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//- (CGFloat)dynamic
|
||||
//{
|
||||
// return 0.75f;
|
||||
//}
|
||||
|
||||
- (bool)arrow
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
- (CGImageRef)generateRadialStampForSize:(CGSize)size hardness:(CGFloat)hardness
|
||||
{
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
|
||||
CGContextRef ctx = CGBitmapContextCreate(NULL, (NSInteger)size.width, (NSInteger)size.height, 8, (NSInteger)size.width, colorspace, kCGImageAlphaNone);
|
||||
|
||||
CGContextSetGrayFillColor(ctx, 0.0f, 1.0f);
|
||||
CGContextFillRect(ctx, CGRectMake(0, 0, size.width, size.height));
|
||||
|
||||
NSArray *colors = @[(__bridge id) [UIColor whiteColor].CGColor, (__bridge id) [UIColor blackColor].CGColor];
|
||||
const CGFloat locations[] = {0.0, 1.0};
|
||||
|
||||
CGGradientRef gradientRef = CGGradientCreateWithColors(colorspace, (__bridge CFArrayRef) colors, locations);
|
||||
CGPoint center = CGPointMake(size.width / 2, size.height / 2);
|
||||
|
||||
CGFloat maxRadius = size.width / 2;
|
||||
CGFloat hFactor = hardness * 0.99;
|
||||
CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation |kCGGradientDrawsAfterEndLocation;
|
||||
CGContextDrawRadialGradient(ctx, gradientRef, center, hFactor * maxRadius, center, maxRadius, options);
|
||||
|
||||
CGImageRef image = CGBitmapContextCreateImage(ctx);
|
||||
|
||||
CGContextRelease(ctx);
|
||||
CGColorSpaceRelease(colorspace);
|
||||
CGGradientRelease(gradientRef);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
- (CGImageRef)stampRef
|
||||
{
|
||||
static CGImageRef image = NULL;
|
||||
|
||||
if (image == NULL)
|
||||
image = [self generateRadialStampForSize:TGPaintBrushTextureSize hardness:TGPaintArrowBrushHardness];
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
- (CGImageRef)previewStampRef
|
||||
{
|
||||
if (_previewStampRef == NULL)
|
||||
_previewStampRef = [self generateRadialStampForSize:TGPaintBrushPreviewTextureSize hardness:TGPaintArrowBrushHardness];
|
||||
|
||||
return _previewStampRef;
|
||||
}
|
||||
|
||||
static UIImage *radialBrushPreviewImage = nil;
|
||||
|
||||
- (UIImage *)previewImage
|
||||
{
|
||||
return radialBrushPreviewImage;
|
||||
}
|
||||
|
||||
- (void)setPreviewImage:(UIImage *)previewImage
|
||||
{
|
||||
radialBrushPreviewImage = previewImage;
|
||||
}
|
||||
|
||||
@end
|
@ -10,7 +10,9 @@
|
||||
@property (nonatomic, readonly) CGFloat alpha;
|
||||
@property (nonatomic, readonly) CGFloat angle;
|
||||
@property (nonatomic, readonly) CGFloat scale;
|
||||
@property (nonatomic, readonly) CGFloat dynamic;
|
||||
@property (nonatomic, readonly) bool lightSaber;
|
||||
@property (nonatomic, readonly) bool arrow;
|
||||
|
||||
@property (nonatomic, readonly) CGImageRef stampRef;
|
||||
@property (nonatomic, readonly) CGImageRef previewStampRef;
|
||||
@ -20,4 +22,4 @@
|
||||
@end
|
||||
|
||||
extern const CGSize TGPaintBrushTextureSize;
|
||||
extern const CGSize TGPaintBrushPreviewTextureSize;
|
||||
extern const CGSize TGPaintBrushPreviewTextureSize;
|
||||
|
@ -61,6 +61,11 @@ const CGSize TGPaintBrushPreviewTextureSize = { 64.0f, 64.0f };
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
- (CGFloat)dynamic
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
- (bool)lightSaber
|
||||
{
|
||||
return false;
|
||||
|
@ -283,10 +283,11 @@ const NSUInteger TGPaintBrushPreviewSegmentsCount = 100;
|
||||
[self _setupBrush];
|
||||
[_renderState reset];
|
||||
_path.remainder = 0.0f;
|
||||
_path.pressureRemainder = 0.0f;
|
||||
_path.brush = brush;
|
||||
|
||||
[TGPaintRender renderPath:_path renderState:_renderState];
|
||||
|
||||
|
||||
if (_brush.lightSaber)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _lightFramebuffer);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#import "TGPaintPath.h"
|
||||
#import "TGPaintState.h"
|
||||
#import "TGPaintCanvas.h"
|
||||
#import "TGPaintBrush.h"
|
||||
#import <LegacyComponents/TGPaintUtils.h>
|
||||
|
||||
@interface TGPaintInput ()
|
||||
@ -19,6 +20,8 @@
|
||||
|
||||
CGPoint _lastLocation;
|
||||
CGFloat _lastRemainder;
|
||||
CGFloat _lastPressureRemainder;
|
||||
CGFloat _lastAngle;
|
||||
|
||||
TGPaintPoint *_points[3];
|
||||
NSInteger _pointsCount;
|
||||
@ -48,7 +51,7 @@
|
||||
CGPoint midPoint1 = TGPaintMultiplyPoint(TGPaintAddPoints(prev1.CGPoint, prev2.CGPoint), 0.5f);
|
||||
CGFloat midPressure1 = (prev1.z + prev2.z) * 0.5f;
|
||||
CGPoint midPoint2 = TGPaintMultiplyPoint(TGPaintAddPoints(cur.CGPoint, prev1.CGPoint), 0.5f);
|
||||
CGFloat midPressure2 = (cur.z + prev2.z) * 0.5f;
|
||||
CGFloat midPressure2 = (cur.z + prev1.z) * 0.5f;
|
||||
|
||||
NSInteger segmentDistance = 2;
|
||||
CGFloat distance = TGPaintDistance(midPoint1, midPoint2);
|
||||
@ -126,12 +129,15 @@
|
||||
if (_pointsCount != 0)
|
||||
pressure = (pressure + _points[_pointsCount - 1].z) / 2.0f;
|
||||
|
||||
pressure = 1.0f;
|
||||
TGPaintPoint *point = [TGPaintPoint pointWithX:location.x y:location.y z:pressure];
|
||||
_points[_pointsCount++] = point;
|
||||
|
||||
if (_pointsCount == 3)
|
||||
{
|
||||
CGPoint prev = _points[1].CGPoint;
|
||||
CGPoint cur = _points[2].CGPoint;
|
||||
_lastAngle = atan2(cur.y - prev.y, cur.x - prev.x);
|
||||
|
||||
[self smoothenAndPaintPoints:canvas ended:false];
|
||||
_moved = true;
|
||||
}
|
||||
@ -156,6 +162,22 @@
|
||||
else
|
||||
{
|
||||
[self smoothenAndPaintPoints:canvas ended:true];
|
||||
|
||||
if (canvas.state.brush.arrow) {
|
||||
CGFloat arrowLength = canvas.state.weight * 4.5;
|
||||
CGFloat angle = _lastAngle;
|
||||
|
||||
TGPaintPoint *tip = [TGPaintPoint pointWithX:location.x y:location.y z:0.8];
|
||||
TGPaintPoint *leftTip = [TGPaintPoint pointWithX:location.x + cos(angle - M_PI_4 * 3) * arrowLength y:location.y + sin(angle - M_PI_4 * 3.2) * arrowLength z:1.0];
|
||||
leftTip.edge = true;
|
||||
TGPaintPath *left = [[TGPaintPath alloc] initWithPoints:@[tip, leftTip]];
|
||||
[self paintPath:left inCanvas:canvas];
|
||||
|
||||
TGPaintPoint *rightTip = [TGPaintPoint pointWithX:location.x + cos(angle + M_PI_4 * 3) * arrowLength y:location.y + sin(angle + M_PI_4 * 3.2) * arrowLength z:1.0];
|
||||
rightTip.edge = true;
|
||||
TGPaintPath *right = [[TGPaintPath alloc] initWithPoints:@[tip, rightTip]];
|
||||
[self paintPath:right inCanvas:canvas];
|
||||
}
|
||||
}
|
||||
|
||||
_pointsCount = 0;
|
||||
@ -181,16 +203,20 @@
|
||||
path.brush = canvas.state.brush;
|
||||
path.baseWeight = canvas.state.weight;
|
||||
|
||||
if (_clearBuffer)
|
||||
if (_clearBuffer) {
|
||||
_lastRemainder = 0.0f;
|
||||
_lastPressureRemainder = 0.0f;
|
||||
}
|
||||
|
||||
path.remainder = _lastRemainder;
|
||||
path.pressureRemainder = _lastPressureRemainder;
|
||||
|
||||
[canvas.painting paintStroke:path clearBuffer:_clearBuffer completion:^
|
||||
{
|
||||
TGDispatchOnMainThread(^
|
||||
{
|
||||
_lastRemainder = path.remainder;
|
||||
_lastPressureRemainder = path.pressureRemainder;
|
||||
_clearBuffer = false;
|
||||
});
|
||||
}];
|
||||
|
@ -43,6 +43,7 @@ typedef enum
|
||||
@property (nonatomic, strong) TGPaintBrush *brush;
|
||||
|
||||
@property (nonatomic, assign) CGFloat remainder;
|
||||
@property (nonatomic, assign) CGFloat pressureRemainder;
|
||||
|
||||
- (instancetype)initWithPoint:(TGPaintPoint *)point;
|
||||
- (instancetype)initWithPoints:(NSArray *)points;
|
||||
|
@ -19,6 +19,11 @@ const CGFloat TGPaintRadialBrushHardness = 0.92f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//- (CGFloat)dynamic
|
||||
//{
|
||||
// return 0.75f;
|
||||
//}
|
||||
|
||||
- (CGImageRef)generateRadialStampForSize:(CGSize)size hardness:(CGFloat)hardness
|
||||
{
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
|
||||
|
@ -14,6 +14,7 @@ const NSInteger TGPaintRenderStateDefaultSize = 256;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign) CGFloat brushWeight;
|
||||
@property (nonatomic, assign) CGFloat brushDynamic;
|
||||
@property (nonatomic, assign) CGFloat spacing;
|
||||
@property (nonatomic, assign) CGFloat alpha;
|
||||
@property (nonatomic, assign) CGFloat angle;
|
||||
@ -23,6 +24,7 @@ const NSInteger TGPaintRenderStateDefaultSize = 256;
|
||||
@property (nonatomic, readonly) NSUInteger count;
|
||||
|
||||
@property (nonatomic, assign) CGFloat remainder;
|
||||
@property (nonatomic, assign) CGFloat pressureRemainder;
|
||||
|
||||
- (void)reset;
|
||||
|
||||
@ -103,6 +105,7 @@ const NSInteger TGPaintRenderStateDefaultSize = 256;
|
||||
}
|
||||
|
||||
_remainder = 0;
|
||||
_pressureRemainder = 0;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -120,18 +123,15 @@ typedef struct
|
||||
|
||||
+ (void)_paintStamp:(TGPaintPoint *)point state:(TGPaintRenderState *)state
|
||||
{
|
||||
CGFloat weight = state.brushWeight;
|
||||
|
||||
CGPoint start = point.CGPoint;
|
||||
|
||||
CGFloat brushSize = weight;
|
||||
CGFloat rotationalScatter = 0.0f;
|
||||
CGFloat brushSize = state.brushWeight * state.scale;
|
||||
CGFloat angleOffset = fabs(state.angle) > FLT_EPSILON ? state.angle : 0.0f;
|
||||
CGFloat alpha = MIN(1.0f, state.alpha * 1.55f);
|
||||
|
||||
[state prepare];
|
||||
[state appendValuesCount:1];
|
||||
[state addPoint:start size:brushSize angle:rotationalScatter + angleOffset alpha:alpha index:0];
|
||||
[state appendValuesCount:4];
|
||||
for (NSInteger i = 0; i < 4; i++) {
|
||||
[state addPoint:point.CGPoint size:brushSize angle:angleOffset alpha:alpha index:i];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_paintFromPoint:(TGPaintPoint *)lastLocation toPoint:(TGPaintPoint *)location state:(TGPaintRenderState *)state
|
||||
@ -139,6 +139,7 @@ typedef struct
|
||||
CGFloat lastP = lastLocation.z;
|
||||
CGFloat p = location.z;
|
||||
CGFloat pDelta = p - lastP;
|
||||
CGFloat pChange = 0.0f;
|
||||
|
||||
CGFloat f, distance = TGPaintDistance(lastLocation.CGPoint, location.CGPoint);
|
||||
CGPoint vector = TGPaintSubtractPoints(location.CGPoint, lastLocation.CGPoint);
|
||||
@ -148,8 +149,8 @@ typedef struct
|
||||
CGFloat brushWeight = state.brushWeight * state.scale;
|
||||
CGFloat step = MAX(1.0f, state.spacing * brushWeight);
|
||||
|
||||
CGFloat pressure = lastP;
|
||||
CGFloat pressureStep = 0.0f;
|
||||
CGFloat pressure = lastP + state.pressureRemainder;
|
||||
CGFloat pressureStep = pressureStep = pDelta / ((distance - state.remainder) / step);
|
||||
|
||||
if (distance > 0.0f)
|
||||
unitVector = TGPaintMultiplyPoint(vector, 1.0f / distance);
|
||||
@ -168,27 +169,29 @@ typedef struct
|
||||
for (f = state.remainder; f <= distance; f += step, pressure += pressureStep)
|
||||
{
|
||||
CGFloat alpha = boldenFirst ? boldenedAlpha : state.alpha;
|
||||
CGFloat brushSize = brushWeight;
|
||||
// CGFloat brushSize = MIN(brushWeight, brushWeight - pressure * brushWeight * 0.55f);
|
||||
CGFloat brushSize = MAX(1.0, brushWeight - state.brushDynamic * pressure * brushWeight);
|
||||
// CGFloat brushSize = brushWeight;
|
||||
[state addPoint:start size:brushSize angle:vectorAngle alpha:alpha index:i];
|
||||
|
||||
start = TGPaintAddPoints(start, TGPaintMultiplyPoint(unitVector, step));
|
||||
|
||||
i++;
|
||||
|
||||
|
||||
boldenFirst = false;
|
||||
|
||||
pressureStep = pDelta / (distance / step);
|
||||
pChange += pressureStep;
|
||||
|
||||
i++;
|
||||
}
|
||||
// NSLog(@"final pressure %f", pressure);
|
||||
|
||||
if (boldenLast)
|
||||
{
|
||||
[state appendValuesCount:1];
|
||||
CGFloat brushSize = MIN(brushWeight, brushWeight - pressure * brushWeight * 0.65f);
|
||||
CGFloat brushSize = MAX(1.0, brushWeight - state.brushDynamic * pressure * brushWeight);
|
||||
[state addPoint:location.CGPoint size:brushSize angle:vectorAngle alpha:boldenedAlpha index:i];
|
||||
}
|
||||
|
||||
state.remainder = f - distance;
|
||||
state.pressureRemainder = pChange - pDelta;
|
||||
}
|
||||
|
||||
+ (CGRect)_drawWithState:(TGPaintRenderState *)state
|
||||
@ -292,6 +295,7 @@ typedef struct
|
||||
+ (CGRect)renderPath:(TGPaintPath *)path renderState:(TGPaintRenderState *)renderState
|
||||
{
|
||||
renderState.brushWeight = path.baseWeight;
|
||||
renderState.brushDynamic = path.brush.dynamic;
|
||||
renderState.spacing = path.brush.spacing;
|
||||
renderState.alpha = path.brush.alpha;
|
||||
renderState.angle = path.brush.angle;
|
||||
@ -313,6 +317,7 @@ typedef struct
|
||||
}
|
||||
|
||||
path.remainder = renderState.remainder;
|
||||
path.pressureRemainder = renderState.pressureRemainder;
|
||||
|
||||
return [self _drawWithState:renderState];
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
@interface TGPaintSwatch : NSObject
|
||||
|
||||
@property (nonatomic, readonly) UIColor *color;
|
||||
@property (nonatomic, readonly) CGFloat colorLocaton;
|
||||
@property (nonatomic, readonly) CGFloat colorLocation;
|
||||
@property (nonatomic, readonly) CGFloat brushWeight;
|
||||
|
||||
+ (instancetype)swatchWithColor:(UIColor *)color colorLocation:(CGFloat)colorLocation brushWeight:(CGFloat)brushWeight;
|
||||
|
@ -11,14 +11,14 @@
|
||||
return false;
|
||||
|
||||
TGPaintSwatch *swatch = (TGPaintSwatch *)object;
|
||||
return [swatch.color isEqual:self.color] && fabs(swatch.colorLocaton - self.colorLocaton) < FLT_EPSILON && fabs(swatch.brushWeight - self.brushWeight) < FLT_EPSILON;
|
||||
return [swatch.color isEqual:self.color] && fabs(swatch.colorLocation - self.colorLocation) < FLT_EPSILON && fabs(swatch.brushWeight - self.brushWeight) < FLT_EPSILON;
|
||||
}
|
||||
|
||||
+ (instancetype)swatchWithColor:(UIColor *)color colorLocation:(CGFloat)colorLocation brushWeight:(CGFloat)brushWeight
|
||||
{
|
||||
TGPaintSwatch *swatch = [[TGPaintSwatch alloc] init];
|
||||
swatch->_color = color;
|
||||
swatch->_colorLocaton = colorLocation;
|
||||
swatch->_colorLocation = colorLocation;
|
||||
swatch->_brushWeight = brushWeight;
|
||||
|
||||
return swatch;
|
||||
|
@ -10,19 +10,20 @@
|
||||
#import "TGPaintBrush.h"
|
||||
#import "TGPaintBrushPreview.h"
|
||||
|
||||
const CGFloat TGPhotoBrushSettingsViewMargin = 19.0f;
|
||||
const CGFloat TGPhotoBrushSettingsViewMargin = 10.0f;
|
||||
const CGFloat TGPhotoBrushSettingsItemHeight = 44.0f;
|
||||
|
||||
@interface TGPhotoBrushSettingsView ()
|
||||
{
|
||||
NSArray *_brushes;
|
||||
TGPaintBrushPreview *_preview;
|
||||
|
||||
UIImageView *_backgroundView;
|
||||
UIView *_wrapperView;
|
||||
UIView *_contentView;
|
||||
UIVisualEffectView *_effectView;
|
||||
|
||||
NSArray *_brushViews;
|
||||
NSArray *_brushIconViews;
|
||||
NSArray *_brushSeparatorViews;
|
||||
UIImageView *_selectedCheckView;
|
||||
|
||||
UIImage *_landscapeLeftBackgroundImage;
|
||||
UIImage *_landscapeRightBackgroundImage;
|
||||
@ -40,80 +41,110 @@ const CGFloat TGPhotoBrushSettingsItemHeight = 44.0f;
|
||||
if (self != nil)
|
||||
{
|
||||
_brushes = brushes;
|
||||
_preview = preview;
|
||||
|
||||
_interfaceOrientation = UIInterfaceOrientationPortrait;
|
||||
|
||||
_backgroundView = [[UIImageView alloc] init];
|
||||
//_backgroundView.alpha = 0.98f;
|
||||
[self addSubview:_backgroundView];
|
||||
_wrapperView = [[UIView alloc] init];
|
||||
_wrapperView.clipsToBounds = true;
|
||||
_wrapperView.layer.cornerRadius = 12.0;
|
||||
[self addSubview:_wrapperView];
|
||||
|
||||
_effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
|
||||
_effectView.alpha = 0.0f;
|
||||
_effectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_wrapperView addSubview:_effectView];
|
||||
|
||||
_contentView = [[UIView alloc] init];
|
||||
_contentView.alpha = 0.0f;
|
||||
_contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_wrapperView addSubview:_contentView];
|
||||
|
||||
UIFont *font = [UIFont systemFontOfSize:17];
|
||||
|
||||
NSMutableArray *brushViews = [[NSMutableArray alloc] init];
|
||||
NSMutableArray *brushIconViews = [[NSMutableArray alloc] init];
|
||||
NSMutableArray *separatorViews = [[NSMutableArray alloc] init];
|
||||
[brushes enumerateObjectsUsingBlock:^(__unused TGPaintBrush *brush, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
TGModernButton *button = [[TGModernButton alloc] initWithFrame:CGRectMake(0, TGPhotoBrushSettingsViewMargin + index * TGPhotoBrushSettingsItemHeight, 0, 0)];
|
||||
button.tag = index;
|
||||
button.imageView.contentMode = UIViewContentModeCenter;
|
||||
button.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 30.0f, 0.0f, 0.0f);
|
||||
[button addTarget:self action:@selector(brushButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:button];
|
||||
NSString *title;
|
||||
UIImage *icon;
|
||||
switch (index) {
|
||||
case 0:
|
||||
title = TGLocalized(@"Paint.Pen");
|
||||
icon = [UIImage imageNamed:@"Editor/BrushPen"];
|
||||
break;
|
||||
case 1:
|
||||
title = TGLocalized(@"Paint.Marker");
|
||||
icon = [UIImage imageNamed:@"Editor/BrushMarker"];
|
||||
break;
|
||||
case 2:
|
||||
title = TGLocalized(@"Paint.Neon");
|
||||
icon = [UIImage imageNamed:@"Editor/BrushNeon"];
|
||||
break;
|
||||
case 3:
|
||||
title = TGLocalized(@"Paint.Arrow");
|
||||
icon = [UIImage imageNamed:@"Editor/BrushArrow"];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TGModernButton *button = [[TGModernButton alloc] initWithFrame:CGRectMake(0, index * TGPhotoBrushSettingsItemHeight, 0, 0)];
|
||||
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
button.titleLabel.font = font;
|
||||
button.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 16.0f, 0.0f, 0.0f);
|
||||
button.tag = index;
|
||||
[button setTitle:title forState:UIControlStateNormal];
|
||||
[button setTitleColor:[UIColor whiteColor]];
|
||||
[button addTarget:self action:@selector(brushButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_contentView addSubview:button];
|
||||
[brushViews addObject:button];
|
||||
|
||||
UIImageView *iconView = [[UIImageView alloc] initWithImage:TGTintedImage(icon, [UIColor whiteColor])];
|
||||
[button addSubview:iconView];
|
||||
[brushIconViews addObject:iconView];
|
||||
|
||||
if (index != brushes.count - 1)
|
||||
{
|
||||
UIView *separatorView = [[UIView alloc] init];
|
||||
separatorView.backgroundColor = UIColorRGB(0xd6d6da);
|
||||
[self addSubview:separatorView];
|
||||
separatorView.backgroundColor = UIColorRGBA(0xffffff, 0.2);
|
||||
[_contentView addSubview:separatorView];
|
||||
|
||||
[separatorViews addObject:separatorView];
|
||||
}
|
||||
}];
|
||||
|
||||
_brushViews = brushViews;
|
||||
_brushIconViews = brushIconViews;
|
||||
_brushSeparatorViews = separatorViews;
|
||||
|
||||
_selectedCheckView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"PaintCheck")];
|
||||
_selectedCheckView.frame = CGRectMake(15.0f, 16.0f, _selectedCheckView.frame.size.width, _selectedCheckView.frame.size.height);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)brushButtonPressed:(TGModernButton *)sender
|
||||
{
|
||||
[sender addSubview:_selectedCheckView];
|
||||
|
||||
if (self.brushChanged != nil)
|
||||
self.brushChanged(_brushes[sender.tag]);
|
||||
}
|
||||
|
||||
- (void)present
|
||||
{
|
||||
self.alpha = 0.0f;
|
||||
|
||||
self.layer.rasterizationScale = TGScreenScaling();
|
||||
self.layer.shouldRasterize = true;
|
||||
|
||||
[self _setupBrushPreviews];
|
||||
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
[UIView animateWithDuration:0.25 animations:^
|
||||
{
|
||||
self.alpha = 1.0f;
|
||||
_effectView.alpha = 1.0f;
|
||||
_contentView.alpha = 1.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
//self.layer.shouldRasterize = false;
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismissWithCompletion:(void (^)(void))completion
|
||||
{
|
||||
self.layer.rasterizationScale = TGScreenScaling();
|
||||
self.layer.shouldRasterize = true;
|
||||
|
||||
[UIView animateWithDuration:0.15 animations:^
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
self.alpha = 0.0f;
|
||||
_effectView.alpha = 0.0f;
|
||||
_contentView.alpha = 0.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
if (completion != nil)
|
||||
@ -121,90 +152,38 @@ const CGFloat TGPhotoBrushSettingsItemHeight = 44.0f;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_setupBrushPreviews
|
||||
{
|
||||
[_brushes enumerateObjectsUsingBlock:^(TGPaintBrush *aBrush, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
UIImage *image = aBrush.previewImage;
|
||||
if (image == nil)
|
||||
{
|
||||
image = [_preview imageForBrush:aBrush size:CGSizeMake([self sizeThatFits:CGSizeZero].width - 85.0f, TGPhotoBrushSettingsItemHeight)];
|
||||
aBrush.previewImage = image;
|
||||
}
|
||||
|
||||
[_brushViews[index] setImage:image forState:UIControlStateNormal];
|
||||
}];
|
||||
}
|
||||
|
||||
- (TGPaintBrush *)brush
|
||||
{
|
||||
return _brushes[_selectedCheckView.superview.tag];
|
||||
}
|
||||
|
||||
- (void)setBrush:(TGPaintBrush *)brush
|
||||
{
|
||||
[_brushes enumerateObjectsUsingBlock:^(TGPaintBrush *aBrush, NSUInteger index, BOOL *stop)
|
||||
{
|
||||
if ([brush isEqual:aBrush])
|
||||
{
|
||||
[_brushViews[index] addSubview:_selectedCheckView];
|
||||
*stop = true;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)__unused size
|
||||
{
|
||||
return CGSizeMake(256, _brushViews.count * TGPhotoBrushSettingsItemHeight + TGPhotoBrushSettingsViewMargin * 2);
|
||||
return CGSizeMake(220, _brushViews.count * TGPhotoBrushSettingsItemHeight + TGPhotoBrushSettingsViewMargin * 2);
|
||||
}
|
||||
|
||||
- (void)setInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
_interfaceOrientation = interfaceOrientation;
|
||||
|
||||
switch (self.interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView landscapeLeftBackgroundImage];
|
||||
}
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView landscapeRightBackgroundImage];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView portraitBackgroundImage];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
CGFloat arrowSize = 0.0f;
|
||||
switch (self.interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
{
|
||||
_backgroundView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin - 13.0f, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2 + 13.0f, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin - arrowSize, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2 + arrowSize, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
{
|
||||
_backgroundView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2 + 13.0f, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2 + arrowSize, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
_backgroundView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2 + 13.0f);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoBrushSettingsViewMargin, TGPhotoBrushSettingsViewMargin, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2, self.frame.size.height - TGPhotoBrushSettingsViewMargin * 2 + arrowSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -213,13 +192,17 @@ const CGFloat TGPhotoBrushSettingsItemHeight = 44.0f;
|
||||
|
||||
[_brushViews enumerateObjectsUsingBlock:^(TGModernButton *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(TGPhotoBrushSettingsViewMargin, TGPhotoBrushSettingsViewMargin + TGPhotoBrushSettingsItemHeight * index, self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2, TGPhotoBrushSettingsItemHeight);
|
||||
|
||||
view.frame = CGRectMake(0.0f, TGPhotoBrushSettingsItemHeight * index, _contentView.frame.size.width, TGPhotoBrushSettingsItemHeight);
|
||||
}];
|
||||
|
||||
[_brushIconViews enumerateObjectsUsingBlock:^(UIImageView *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(_contentView.frame.size.width - 42.0f, (TGPhotoBrushSettingsItemHeight - view.frame.size.height) / 2.0, view.frame.size.width, view.frame.size.height);
|
||||
}];
|
||||
|
||||
[_brushSeparatorViews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(TGPhotoBrushSettingsViewMargin + 44.0f, TGPhotoBrushSettingsViewMargin + TGPhotoBrushSettingsItemHeight * (index + 1), self.frame.size.width - TGPhotoBrushSettingsViewMargin * 2 - 44.0f, thickness);
|
||||
view.frame = CGRectMake(0.0f, TGPhotoBrushSettingsItemHeight * (index + 1), _contentView.frame.size.width, thickness);
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -1552,7 +1552,7 @@
|
||||
if ([item isKindOfClass:[TGMediaAsset class]])
|
||||
assetSignal = [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)item];
|
||||
else if ([item isKindOfClass:[TGCameraCapturedVideo class]])
|
||||
assetSignal = [SSignal single:((TGCameraCapturedVideo *)item).avAsset];
|
||||
assetSignal = ((TGCameraCapturedVideo *)item).avAsset;
|
||||
|
||||
[assetSignal startWithNext:^(AVAsset *asset)
|
||||
{
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
- (void)updateVisibility:(bool)visible;
|
||||
|
||||
- (UIColor *)colorAtPoint:(CGPoint)point;
|
||||
|
||||
- (void)setupWithPaintingData:(TGPaintingData *)paintingData;
|
||||
- (TGPhotoPaintEntityView *)createEntityViewWithEntity:(TGPhotoPaintEntity *)entity;
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
CGPoint location = [gestureRecognizer locationInView:self];
|
||||
CGPoint point = [gestureRecognizer locationInView:self];
|
||||
|
||||
NSMutableArray *intersectedViews = [[NSMutableArray alloc] init];
|
||||
for (TGPhotoPaintEntityView *view in self.subviews)
|
||||
@ -55,7 +55,7 @@
|
||||
if (![view isKindOfClass:[TGPhotoPaintEntityView class]])
|
||||
continue;
|
||||
|
||||
if ([view pointInside:[view convertPoint:location fromView:self] withEvent:nil])
|
||||
if ([view pointInside:[view convertPoint:point fromView:self] withEvent:nil])
|
||||
[intersectedViews addObject:view];
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
__block TGPhotoPaintEntityView *subresult = nil;
|
||||
[intersectedViews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(TGPhotoPaintEntityView *view, __unused NSUInteger index, BOOL *stop)
|
||||
{
|
||||
if ([view precisePointInside:[view convertPoint:location fromView:self]])
|
||||
if ([view precisePointInside:[view convertPoint:point fromView:self]])
|
||||
{
|
||||
subresult = view;
|
||||
*stop = true;
|
||||
@ -83,6 +83,40 @@
|
||||
self.entitySelected(result);
|
||||
}
|
||||
|
||||
- (UIColor *)colorAtPoint:(CGPoint)point {
|
||||
NSMutableArray *intersectedViews = [[NSMutableArray alloc] init];
|
||||
for (TGPhotoPaintEntityView *view in self.subviews)
|
||||
{
|
||||
if (![view isKindOfClass:[TGPhotoPaintEntityView class]])
|
||||
continue;
|
||||
|
||||
if ([view pointInside:[view convertPoint:point fromView:self] withEvent:nil])
|
||||
[intersectedViews addObject:view];
|
||||
}
|
||||
|
||||
TGPhotoPaintEntityView *result = nil;
|
||||
if (intersectedViews.count > 1)
|
||||
{
|
||||
__block TGPhotoPaintEntityView *subresult = nil;
|
||||
[intersectedViews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(TGPhotoPaintEntityView *view, __unused NSUInteger index, BOOL *stop)
|
||||
{
|
||||
if ([view precisePointInside:[view convertPoint:point fromView:self]])
|
||||
{
|
||||
subresult = view;
|
||||
*stop = true;
|
||||
}
|
||||
}];
|
||||
|
||||
result = subresult ?: intersectedViews.lastObject;
|
||||
}
|
||||
else if (intersectedViews.count == 1)
|
||||
{
|
||||
result = intersectedViews.firstObject;
|
||||
}
|
||||
|
||||
return [result colorAtPoint:[result convertPoint:point fromView:self]];
|
||||
}
|
||||
|
||||
- (NSUInteger)entitiesCount
|
||||
{
|
||||
return MAX(0, (NSInteger)self.subviews.count - 1);
|
||||
|
@ -137,7 +137,7 @@ const CGFloat TGPhotoPaintDefaultColorLocation = 1.0f;
|
||||
|
||||
- (void)setSwatch:(TGPaintSwatch *)swatch
|
||||
{
|
||||
[self setLocation:swatch.colorLocaton];
|
||||
[self setLocation:swatch.colorLocation];
|
||||
[self setWeight:swatch.brushWeight];
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#import "TGPaintRadialBrush.h"
|
||||
#import "TGPaintEllipticalBrush.h"
|
||||
#import "TGPaintNeonBrush.h"
|
||||
#import "TGPaintArrowBrush.h"
|
||||
#import "TGPaintCanvas.h"
|
||||
#import "TGPaintingWrapperView.h"
|
||||
#import "TGPaintState.h"
|
||||
@ -45,6 +46,7 @@
|
||||
#import "TGPhotoEntitiesContainerView.h"
|
||||
#import "TGPhotoStickerEntityView.h"
|
||||
#import "TGPhotoTextEntityView.h"
|
||||
#import "TGPhotoPaintEyedropperView.h"
|
||||
|
||||
#import "TGPaintFaceDetector.h"
|
||||
#import "TGPhotoMaskPosition.h"
|
||||
@ -83,6 +85,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
UIView *_contentWrapperView;
|
||||
|
||||
UIView *_dimView;
|
||||
TGModernButton *_doneButton;
|
||||
|
||||
TGPhotoPaintActionsView *_landscapeActionsView;
|
||||
TGPhotoPaintActionsView *_portraitActionsView;
|
||||
@ -104,6 +107,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
TGPhotoPaintSelectionContainerView *_selectionContainerView;
|
||||
TGPhotoPaintEntitySelectionView *_entitySelectionView;
|
||||
TGPhotoPaintEyedropperView *_eyedropperView;
|
||||
|
||||
TGPhotoTextEntityView *_editedTextView;
|
||||
CGPoint _editedTextCenter;
|
||||
@ -122,6 +126,11 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
bool _enableStickers;
|
||||
|
||||
NSData *_eyedropperBackgroundData;
|
||||
CGSize _eyedropperBackgroundSize;
|
||||
NSInteger _eyedropperBackgroundBytesPerRow;
|
||||
CGBitmapInfo _eyedropperBackgroundInfo;
|
||||
|
||||
id<LegacyComponentsContext> _context;
|
||||
}
|
||||
|
||||
@ -151,10 +160,11 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[
|
||||
[[TGPaintRadialBrush alloc] init],
|
||||
[[TGPaintEllipticalBrush alloc] init],
|
||||
[[TGPaintNeonBrush alloc] init]
|
||||
[[TGPaintNeonBrush alloc] init],
|
||||
[[TGPaintArrowBrush alloc] init],
|
||||
];
|
||||
_selectedTextFont = [[TGPhotoPaintFont availableFonts] firstObject];
|
||||
_selectedTextStyle = TGPhotoPaintTextEntityStyleBorder;
|
||||
_selectedTextStyle = TGPhotoPaintTextEntityStyleFramed;
|
||||
|
||||
if (_photoEditor.paintingData.undoManager != nil)
|
||||
_undoManager = [_photoEditor.paintingData.undoManager copy];
|
||||
@ -265,11 +275,30 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
_dimView.backgroundColor = UIColorRGBA(0x000000, 0.4f);
|
||||
_dimView.userInteractionEnabled = false;
|
||||
[_entitiesContainerView addSubview:_dimView];
|
||||
|
||||
|
||||
_selectionContainerView = [[TGPhotoPaintSelectionContainerView alloc] init];
|
||||
_selectionContainerView.clipsToBounds = false;
|
||||
[_containerView addSubview:_selectionContainerView];
|
||||
|
||||
_eyedropperView = [[TGPhotoPaintEyedropperView alloc] init];
|
||||
_eyedropperView.locationChanged = ^(CGPoint location, bool finished) {
|
||||
__strong TGPhotoPaintController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
UIColor *color = [strongSelf colorAtPoint:location];
|
||||
strongSelf->_eyedropperView.color = color;
|
||||
|
||||
if (finished) {
|
||||
TGPaintSwatch *swatch = [TGPaintSwatch swatchWithColor:color colorLocation:0.5 brushWeight:strongSelf->_portraitSettingsView.swatch.brushWeight];
|
||||
[strongSelf setCurrentSwatch:swatch sender:nil];
|
||||
|
||||
[strongSelf commitEyedropper:false];
|
||||
}
|
||||
}
|
||||
};
|
||||
_eyedropperView.hidden = true;
|
||||
[_selectionContainerView addSubview:_eyedropperView];
|
||||
|
||||
_wrapperView = [[TGPhotoPaintSparseView alloc] initWithFrame:CGRectZero];
|
||||
[self.view addSubview:_wrapperView];
|
||||
|
||||
@ -307,12 +336,22 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
_landscapeActionsView.clearPressed = clearPressed;
|
||||
[_wrapperView addSubview:_landscapeActionsView];
|
||||
|
||||
_doneButton = [[TGModernButton alloc] init];
|
||||
_doneButton.alpha = 0.0f;
|
||||
_doneButton.userInteractionEnabled = false;
|
||||
[_doneButton setTitle:TGLocalized(@"Common.Done") forState:UIControlStateNormal];
|
||||
_doneButton.titleLabel.font = TGSystemFontOfSize(17.0);
|
||||
[_doneButton sizeToFit];
|
||||
[_wrapperView addSubview:_doneButton];
|
||||
|
||||
void (^settingsPressed)(void) = ^
|
||||
{
|
||||
__strong TGPhotoPaintController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[strongSelf commitEyedropper:true];
|
||||
|
||||
if ([strongSelf->_currentEntityView isKindOfClass:[TGPhotoTextEntityView class]])
|
||||
[strongSelf presentTextSettingsView];
|
||||
else if ([strongSelf->_currentEntityView isKindOfClass:[TGPhotoStickerEntityView class]])
|
||||
@ -321,11 +360,22 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[strongSelf presentBrushSettingsView];
|
||||
};
|
||||
|
||||
void (^eyedropperPressed)(void) = ^
|
||||
{
|
||||
__strong TGPhotoPaintController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[self enableEyedropper];
|
||||
};
|
||||
|
||||
void (^beganColorPicking)(void) = ^
|
||||
{
|
||||
__strong TGPhotoPaintController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[strongSelf commitEyedropper:true];
|
||||
|
||||
if (![strongSelf->_currentEntityView isKindOfClass:[TGPhotoTextEntityView class]])
|
||||
[strongSelf setDimHidden:false animated:true];
|
||||
@ -346,6 +396,8 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
[strongSelf commitEyedropper:true];
|
||||
|
||||
[strongSelf setCurrentSwatch:swatch sender:sender];
|
||||
|
||||
if (![strongSelf->_currentEntityView isKindOfClass:[TGPhotoTextEntityView class]])
|
||||
@ -353,6 +405,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
};
|
||||
|
||||
_portraitSettingsView = [[TGPhotoPaintSettingsView alloc] initWithContext:_context];
|
||||
_portraitSettingsView.eyedropperPressed = eyedropperPressed;
|
||||
_portraitSettingsView.beganColorPicking = beganColorPicking;
|
||||
_portraitSettingsView.changedColor = changedColor;
|
||||
_portraitSettingsView.finishedColorPicking = finishedColorPicking;
|
||||
@ -362,6 +415,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[_portraitToolsWrapperView addSubview:_portraitSettingsView];
|
||||
|
||||
_landscapeSettingsView = [[TGPhotoPaintSettingsView alloc] initWithContext:_context];
|
||||
_landscapeSettingsView.eyedropperPressed = eyedropperPressed;
|
||||
_landscapeSettingsView.beganColorPicking = beganColorPicking;
|
||||
_landscapeSettingsView.changedColor = changedColor;
|
||||
_landscapeSettingsView.finishedColorPicking = finishedColorPicking;
|
||||
@ -497,6 +551,8 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
- (void)handleTabAction:(TGPhotoEditorTab)tab
|
||||
{
|
||||
[self commitEyedropper:true];
|
||||
|
||||
switch (tab)
|
||||
{
|
||||
case TGPhotoEditorStickerTab:
|
||||
@ -625,6 +681,49 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
#pragma mark - Data Handling
|
||||
|
||||
- (UIImage *)eyedropperImage
|
||||
{
|
||||
UIImage *backgroundImage = [self.photoEditor currentResultImage];
|
||||
|
||||
CGSize fittedSize = TGFitSize(_painting.size, TGPhotoEditorResultImageMaxSize);
|
||||
UIImage *paintingImage = _painting.isEmpty ? nil : [_painting imageWithSize:fittedSize andData:NULL];
|
||||
NSMutableArray *entities = [[NSMutableArray alloc] init];
|
||||
|
||||
UIImage *entitiesImage = nil;
|
||||
if (paintingImage == nil && _entitiesContainerView.entitiesCount < 1)
|
||||
{
|
||||
return backgroundImage;
|
||||
}
|
||||
else if (_entitiesContainerView.entitiesCount > 0)
|
||||
{
|
||||
for (TGPhotoPaintEntityView *view in _entitiesContainerView.subviews)
|
||||
{
|
||||
if (![view isKindOfClass:[TGPhotoPaintEntityView class]])
|
||||
continue;
|
||||
|
||||
TGPhotoPaintEntity *entity = [view entity];
|
||||
if (entity != nil) {
|
||||
[entities addObject:entity];
|
||||
}
|
||||
}
|
||||
entitiesImage = [_entitiesContainerView imageInRect:_entitiesContainerView.bounds background:nil still:true];
|
||||
}
|
||||
|
||||
if (entitiesImage == nil && paintingImage == nil) {
|
||||
return backgroundImage;
|
||||
} else {
|
||||
UIGraphicsBeginImageContextWithOptions(fittedSize, false, 1.0);
|
||||
|
||||
[backgroundImage drawInRect:CGRectMake(0.0, 0.0, fittedSize.width, fittedSize.height)];
|
||||
[paintingImage drawInRect:CGRectMake(0.0, 0.0, fittedSize.width, fittedSize.height)];
|
||||
[entitiesImage drawInRect:CGRectMake(0.0, 0.0, fittedSize.width, fittedSize.height)];
|
||||
|
||||
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
- (TGPaintingData *)_prepareResultData
|
||||
{
|
||||
if (_resultData != nil)
|
||||
@ -698,6 +797,60 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
return [self _prepareResultData];
|
||||
}
|
||||
|
||||
- (void)enableEyedropper {
|
||||
if (!_eyedropperView.isHidden)
|
||||
return;
|
||||
|
||||
[self selectEntityView:nil];
|
||||
|
||||
self.controlVideoPlayback(false);
|
||||
[_entitiesContainerView updateVisibility:false];
|
||||
|
||||
UIImage *image = [self eyedropperImage];
|
||||
CGImageRef cgImage = image.CGImage;
|
||||
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
|
||||
|
||||
_eyedropperBackgroundData = (__bridge NSData *)pixelData;
|
||||
_eyedropperBackgroundSize = image.size;
|
||||
_eyedropperBackgroundBytesPerRow = CGImageGetBytesPerRow(cgImage);
|
||||
_eyedropperBackgroundInfo = CGImageGetBitmapInfo(cgImage);
|
||||
|
||||
[_eyedropperView update];
|
||||
[_eyedropperView present];
|
||||
}
|
||||
|
||||
- (void)commitEyedropper:(bool)immediate {
|
||||
self.controlVideoPlayback(true);
|
||||
[_entitiesContainerView updateVisibility:true];
|
||||
|
||||
_eyedropperBackgroundData = nil;
|
||||
_eyedropperBackgroundSize = CGSizeZero;
|
||||
_eyedropperBackgroundBytesPerRow = 0;
|
||||
_eyedropperBackgroundInfo = 0;
|
||||
|
||||
double timeout = immediate ? 0.0 : 0.2;
|
||||
TGDispatchAfter(timeout, dispatch_get_main_queue(), ^{
|
||||
[_eyedropperView dismiss];
|
||||
});
|
||||
}
|
||||
|
||||
- (UIColor *)colorFromData:(NSData *)data width:(NSInteger)width height:(NSInteger)height x:(NSInteger)x y:(NSInteger)y bpr:(NSInteger)bpr {
|
||||
uint8_t *pixel = (uint8_t *)data.bytes + bpr * y + x * 4;
|
||||
if (_eyedropperBackgroundInfo & kCGBitmapByteOrder32Little) {
|
||||
return [UIColor colorWithRed:pixel[2] / 255.0 green:pixel[1] / 255.0 blue:pixel[0] / 255.0 alpha:1.0];
|
||||
} else {
|
||||
return [UIColor colorWithRed:pixel[0] / 255.0 green:pixel[1] / 255.0 blue:pixel[2] / 255.0 alpha:1.0];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIColor *)colorAtPoint:(CGPoint)point
|
||||
{
|
||||
CGPoint convertedPoint = CGPointMake(point.x / _eyedropperView.bounds.size.width * _eyedropperBackgroundSize.width, point.y / _eyedropperView.bounds.size.height * _eyedropperBackgroundSize.height);
|
||||
UIColor *backgroundColor = [self colorFromData:_eyedropperBackgroundData width:_eyedropperBackgroundSize.width height:_eyedropperBackgroundSize.height x:convertedPoint.x y:convertedPoint.y bpr:_eyedropperBackgroundBytesPerRow];
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Entities
|
||||
|
||||
- (void)selectEntityView:(TGPhotoPaintEntityView *)view
|
||||
@ -734,7 +887,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
if ([view isKindOfClass:[TGPhotoTextEntityView class]])
|
||||
{
|
||||
TGPaintSwatch *textSwatch = ((TGPhotoPaintTextEntity *)view.entity).swatch;
|
||||
[self setCurrentSwatch:[TGPaintSwatch swatchWithColor:textSwatch.color colorLocation:textSwatch.colorLocaton brushWeight:_portraitSettingsView.swatch.brushWeight] sender:nil];
|
||||
[self setCurrentSwatch:[TGPaintSwatch swatchWithColor:textSwatch.color colorLocation:textSwatch.colorLocation brushWeight:_portraitSettingsView.swatch.brushWeight] sender:nil];
|
||||
}
|
||||
|
||||
_entitySelectionView = [view createSelectionView];
|
||||
@ -1061,7 +1214,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
TGPaintSwatch *currentSwatch = _portraitSettingsView.swatch;
|
||||
TGPaintSwatch *whiteSwatch = [TGPaintSwatch swatchWithColor:[UIColor whiteColor] colorLocation:1.0f brushWeight:currentSwatch.brushWeight];
|
||||
TGPaintSwatch *blackSwatch = [TGPaintSwatch swatchWithColor:[UIColor blackColor] colorLocation:0.85f brushWeight:currentSwatch.brushWeight];
|
||||
[self setCurrentSwatch:_selectedTextStyle == TGPhotoPaintTextEntityStyleBorder ? blackSwatch : whiteSwatch sender:nil];
|
||||
[self setCurrentSwatch:_selectedTextStyle == TGPhotoPaintTextEntityStyleOutlined ? blackSwatch : whiteSwatch sender:nil];
|
||||
|
||||
CGFloat maxWidth = [self fittedContentSize].width - 26.0f;
|
||||
TGPhotoPaintTextEntity *entity = [[TGPhotoPaintTextEntity alloc] initWithText:@"" font:_selectedTextFont swatch:_portraitSettingsView.swatch baseFontSize:[self _textBaseFontSizeForCurrentPainting] maxWidth:maxWidth style:_selectedTextStyle];
|
||||
@ -1258,13 +1411,35 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
- (void)updateSettingsButton
|
||||
{
|
||||
if ([_currentEntityView isKindOfClass:[TGPhotoTextEntityView class]])
|
||||
[self setSettingsButtonIcon:TGPhotoPaintSettingsViewIconText];
|
||||
else if ([_currentEntityView isKindOfClass:[TGPhotoStickerEntityView class]])
|
||||
if ([_currentEntityView isKindOfClass:[TGPhotoTextEntityView class]]) {
|
||||
TGPhotoPaintSettingsViewIcon icon;
|
||||
switch (((TGPhotoTextEntityView *)_currentEntityView).entity.style) {
|
||||
case TGPhotoPaintTextEntityStyleRegular:
|
||||
icon = TGPhotoPaintSettingsViewIconTextRegular;
|
||||
break;
|
||||
case TGPhotoPaintTextEntityStyleOutlined:
|
||||
icon = TGPhotoPaintSettingsViewIconTextOutlined;
|
||||
break;
|
||||
case TGPhotoPaintTextEntityStyleFramed:
|
||||
icon = TGPhotoPaintSettingsViewIconTextFramed;
|
||||
break;
|
||||
}
|
||||
[self setSettingsButtonIcon:icon];
|
||||
}
|
||||
else if ([_currentEntityView isKindOfClass:[TGPhotoStickerEntityView class]]) {
|
||||
[self setSettingsButtonIcon:TGPhotoPaintSettingsViewIconMirror];
|
||||
else
|
||||
[self setSettingsButtonIcon:TGPhotoPaintSettingsViewIconBrush];
|
||||
|
||||
}
|
||||
else {
|
||||
TGPhotoPaintSettingsViewIcon icon = TGPhotoPaintSettingsViewIconBrushPen;
|
||||
if ([_canvasView.state.brush isKindOfClass:[TGPaintEllipticalBrush class]]) {
|
||||
icon = TGPhotoPaintSettingsViewIconBrushMarker;
|
||||
} else if ([_canvasView.state.brush isKindOfClass:[TGPaintNeonBrush class]]) {
|
||||
icon = TGPhotoPaintSettingsViewIconBrushNeon;
|
||||
} else if ([_canvasView.state.brush isKindOfClass:[TGPaintArrowBrush class]]) {
|
||||
icon = TGPhotoPaintSettingsViewIconBrushArrow;
|
||||
}
|
||||
[self setSettingsButtonIcon:icon];
|
||||
}
|
||||
[self _updateTabs];
|
||||
}
|
||||
|
||||
@ -1347,12 +1522,13 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (strongSelf->_canvasView.state.eraser && brush.lightSaber)
|
||||
if (strongSelf->_canvasView.state.eraser && (brush.lightSaber || brush.arrow))
|
||||
brush = strongSelf->_brushes.firstObject;
|
||||
|
||||
[strongSelf->_canvasView setBrush:brush];
|
||||
|
||||
[strongSelf settingsWrapperPressed];
|
||||
[strongSelf updateSettingsButton];
|
||||
};
|
||||
_settingsView = view;
|
||||
[view sizeToFit];
|
||||
@ -1383,6 +1559,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[textView setFont:font];
|
||||
|
||||
[strongSelf settingsWrapperPressed];
|
||||
[strongSelf updateSettingsButton];
|
||||
};
|
||||
view.styleChanged = ^(TGPhotoPaintTextEntityStyle style)
|
||||
{
|
||||
@ -1392,13 +1569,13 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
strongSelf->_selectedTextStyle = style;
|
||||
|
||||
if (style == TGPhotoPaintTextEntityStyleBorder && [strongSelf->_portraitSettingsView.swatch.color isEqual:[UIColor whiteColor]])
|
||||
if (style == TGPhotoPaintTextEntityStyleOutlined && [strongSelf->_portraitSettingsView.swatch.color isEqual:[UIColor whiteColor]])
|
||||
{
|
||||
TGPaintSwatch *currentSwatch = strongSelf->_portraitSettingsView.swatch;
|
||||
TGPaintSwatch *blackSwatch = [TGPaintSwatch swatchWithColor:[UIColor blackColor] colorLocation:0.85f brushWeight:currentSwatch.brushWeight];
|
||||
[strongSelf setCurrentSwatch:blackSwatch sender:nil];
|
||||
}
|
||||
else if (style != TGPhotoPaintTextEntityStyleBorder && [strongSelf->_portraitSettingsView.swatch.color isEqual:UIColorRGB(0x000000)])
|
||||
else if (style != TGPhotoPaintTextEntityStyleOutlined && [strongSelf->_portraitSettingsView.swatch.color isEqual:UIColorRGB(0x000000)])
|
||||
{
|
||||
TGPaintSwatch *currentSwatch = strongSelf->_portraitSettingsView.swatch;
|
||||
TGPaintSwatch *whiteSwatch = [TGPaintSwatch swatchWithColor:[UIColor whiteColor] colorLocation:1.0f brushWeight:currentSwatch.brushWeight];
|
||||
@ -1409,6 +1586,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[textView setStyle:style];
|
||||
|
||||
[strongSelf settingsWrapperPressed];
|
||||
[strongSelf updateSettingsButton];
|
||||
};
|
||||
|
||||
_settingsView = view;
|
||||
@ -1429,13 +1607,14 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
if (_canvasView.state.eraser)
|
||||
{
|
||||
if (_canvasView.state.brush.lightSaber)
|
||||
if (_canvasView.state.brush.lightSaber || _canvasView.state.brush.arrow)
|
||||
[_canvasView setBrush:_brushes.firstObject];
|
||||
}
|
||||
|
||||
[_portraitSettingsView setHighlighted:_canvasView.state.isEraser];
|
||||
[_landscapeSettingsView setHighlighted:_canvasView.state.isEraser];
|
||||
|
||||
[self updateSettingsButton];
|
||||
[self _updateTabs];
|
||||
}
|
||||
|
||||
@ -1934,17 +2113,22 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
[_dimView.superview insertSubview:_dimView belowSubview:_currentEntityView];
|
||||
else
|
||||
[_dimView.superview bringSubviewToFront:_dimView];
|
||||
|
||||
[_doneButton.superview bringSubviewToFront:_doneButton];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_entitySelectionView fadeIn];
|
||||
|
||||
[_dimView.superview bringSubviewToFront:_dimView];
|
||||
|
||||
[_doneButton.superview bringSubviewToFront:_doneButton];
|
||||
}
|
||||
|
||||
void (^changeBlock)(void) = ^
|
||||
{
|
||||
_dimView.alpha = hidden ? 0.0f : 1.0f;
|
||||
_doneButton.alpha = hidden ? 0.0f : 1.0f;
|
||||
};
|
||||
|
||||
if (animated)
|
||||
@ -2016,6 +2200,8 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
_settingsViewWrapper.frame = self.parentViewController.view.bounds;
|
||||
|
||||
_doneButton.frame = CGRectMake(screenEdges.right - _doneButton.frame.size.width - 8.0, screenEdges.top + 2.0, _doneButton.frame.size.width, _doneButton.frame.size.height);
|
||||
|
||||
if (_settingsView != nil)
|
||||
[_settingsView setInterfaceOrientation:orientation];
|
||||
|
||||
@ -2151,6 +2337,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
_selectionContainerView.transform = CGAffineTransformRotate(rotationTransform, rotation);
|
||||
_selectionContainerView.frame = previewFrame;
|
||||
_eyedropperView.frame = _selectionContainerView.bounds;
|
||||
|
||||
_containerView.frame = CGRectMake(containerFrame.origin.x, containerFrame.origin.y + offsetHeight, containerFrame.size.width, containerFrame.size.height);
|
||||
}
|
||||
|
@ -221,3 +221,27 @@ const CGFloat TGPhotoPaintEntityMinScale = 0.12f;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIView (PixelColor)
|
||||
|
||||
- (UIColor *)colorAtPoint:(CGPoint)point
|
||||
{
|
||||
if (point.x > self.bounds.size.width || point.y > self.bounds.size.height)
|
||||
return nil;
|
||||
|
||||
unsigned char pixel[4] = {0};
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
|
||||
|
||||
CGContextTranslateCTM(context, -point.x, -point.y);
|
||||
|
||||
[self.layer renderInContext:context];
|
||||
|
||||
CGContextRelease(context);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
return [UIColor colorWithRed:pixel[0] / 255.0 green:pixel[1] / 255.0 blue:pixel[2] / 255.0 alpha:pixel[3] / 255.0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -0,0 +1,13 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TGPhotoPaintEyedropperView : UIView
|
||||
|
||||
@property (nonatomic, strong) UIColor *color;
|
||||
@property (nonatomic, copy) void(^locationChanged)(CGPoint, bool);
|
||||
|
||||
- (void)update;
|
||||
- (void)present;
|
||||
- (void)dismiss;
|
||||
|
||||
@end
|
||||
|
157
submodules/LegacyComponents/Sources/TGPhotoPaintEyedropperView.m
Normal file
157
submodules/LegacyComponents/Sources/TGPhotoPaintEyedropperView.m
Normal file
@ -0,0 +1,157 @@
|
||||
#import "TGPhotoPaintEyedropperView.h"
|
||||
|
||||
#import "TGImageUtils.h"
|
||||
|
||||
@interface TGPhotoPaintEyedropperIndicatorView : UIView
|
||||
|
||||
@property (nonatomic, strong) UIColor *color;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGPhotoPaintEyedropperIndicatorView
|
||||
|
||||
-(instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.opaque = false;
|
||||
self.userInteractionEnabled = false;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setColor:(UIColor *)color {
|
||||
_color = color;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGFloat lineWidth = 1.0f + TGScreenPixel;
|
||||
|
||||
CGContextSetFillColorWithColor(context, _color.CGColor);
|
||||
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
|
||||
|
||||
CGContextSaveGState(context);
|
||||
|
||||
CGContextScaleCTM(context, 0.333333, 0.333333);
|
||||
CGContextSetLineWidth(context, lineWidth * 3.0);
|
||||
|
||||
TGDrawSvgPath(context, @"M75,0.5 C54.4273931,0.5 35.8023931,8.83869653 22.3205448,22.3205448 C8.83869653,35.8023931 0.5,54.4273931 0.5,75 C0.5,94.6543797 10.7671345,116.856807 23.8111444,136.192682 C42.4188317,163.77591 66.722394,185.676747 75,185.676747 C83.277606,185.676747 107.581168,163.77591 126.188856,136.192682 C139.232866,116.856807 149.5,94.6543797 149.5,75 C149.5,54.4273931 141.161303,35.8023931 127.679455,22.3205448 C114.197607,8.83869653 95.5726069,0.5 75,0.5 Z");
|
||||
|
||||
TGDrawSvgPath(context, @"M75,0.5 C54.4273931,0.5 35.8023931,8.83869653 22.3205448,22.3205448 C8.83869653,35.8023931 0.5,54.4273931 0.5,75 C0.5,94.6543797 10.7671345,116.856807 23.8111444,136.192682 C42.4188317,163.77591 66.722394,185.676747 75,185.676747 C83.277606,185.676747 107.581168,163.77591 126.188856,136.192682 C139.232866,116.856807 149.5,94.6543797 149.5,75 C149.5,54.4273931 141.161303,35.8023931 127.679455,22.3205448 C114.197607,8.83869653 95.5726069,0.5 75,0.5 S");
|
||||
|
||||
CGContextRestoreGState(context);
|
||||
|
||||
CGContextSetLineWidth(context, lineWidth);
|
||||
CGContextFillEllipseInRect(context, CGRectMake(20.0, 68.0, 11.0, 11.0));
|
||||
CGContextStrokeEllipseInRect(context, CGRectMake(20.0, 68.0, 11.0, 11.0));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface TGPhotoPaintEyedropperView() <UIGestureRecognizerDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation TGPhotoPaintEyedropperView
|
||||
{
|
||||
TGPhotoPaintEyedropperIndicatorView *_indicatorView;
|
||||
|
||||
UITapGestureRecognizer *_tapGestureRecognizer;
|
||||
UIPanGestureRecognizer *_panGestureRecognizer;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil) {
|
||||
_indicatorView = [[TGPhotoPaintEyedropperIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 51.0, 81.0)];
|
||||
_indicatorView.layer.anchorPoint = CGPointMake(0.5, 0.92);
|
||||
[self addSubview:_indicatorView];
|
||||
|
||||
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
||||
[self addGestureRecognizer:_tapGestureRecognizer];
|
||||
|
||||
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
|
||||
_panGestureRecognizer.delegate = self;
|
||||
[self addGestureRecognizer:_panGestureRecognizer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setColor:(UIColor *)color {
|
||||
_color = color;
|
||||
_indicatorView.color = color;
|
||||
}
|
||||
|
||||
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer {
|
||||
CGPoint location = [gestureRecognizer locationInView:self];
|
||||
[self layoutIndicator:location];
|
||||
self.locationChanged(location, true);
|
||||
}
|
||||
|
||||
- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer {
|
||||
CGPoint location = [gestureRecognizer locationInView:self];
|
||||
switch (gestureRecognizer.state)
|
||||
{
|
||||
case UIGestureRecognizerStateChanged:
|
||||
{
|
||||
[self layoutIndicator:location];
|
||||
self.locationChanged(location, false);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case UIGestureRecognizerStateEnded:
|
||||
{
|
||||
[self layoutIndicator:location];
|
||||
self.locationChanged(location, true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
CGPoint location = CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0);
|
||||
self.locationChanged(location, false);
|
||||
[self layoutIndicator:location];
|
||||
}
|
||||
|
||||
- (void)present {
|
||||
self.hidden = false;
|
||||
|
||||
_indicatorView.alpha = 0.0f;
|
||||
_indicatorView.transform = CGAffineTransformMakeScale(0.2, 0.2);
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
_indicatorView.alpha = 1.0f;
|
||||
_indicatorView.transform = CGAffineTransformIdentity;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismiss {
|
||||
if (self.hidden)
|
||||
return;
|
||||
|
||||
[UIView animateWithDuration:0.15 animations:^
|
||||
{
|
||||
_indicatorView.alpha = 0.0f;
|
||||
_indicatorView.transform = CGAffineTransformMakeScale(0.2, 0.2);
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
self.hidden = true;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)layoutIndicator:(CGPoint)point {
|
||||
_indicatorView.center = CGPointMake(point.x, point.y);
|
||||
}
|
||||
|
||||
@end
|
@ -6,8 +6,13 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TGPhotoPaintSettingsViewIconBrush,
|
||||
TGPhotoPaintSettingsViewIconText,
|
||||
TGPhotoPaintSettingsViewIconBrushPen,
|
||||
TGPhotoPaintSettingsViewIconBrushMarker,
|
||||
TGPhotoPaintSettingsViewIconBrushNeon,
|
||||
TGPhotoPaintSettingsViewIconBrushArrow,
|
||||
TGPhotoPaintSettingsViewIconTextRegular,
|
||||
TGPhotoPaintSettingsViewIconTextOutlined,
|
||||
TGPhotoPaintSettingsViewIconTextFramed,
|
||||
TGPhotoPaintSettingsViewIconMirror
|
||||
} TGPhotoPaintSettingsViewIcon;
|
||||
|
||||
@ -17,7 +22,9 @@ typedef enum
|
||||
@property (nonatomic, copy) void (^changedColor)(TGPhotoPaintSettingsView *sender, TGPaintSwatch *swatch);
|
||||
@property (nonatomic, copy) void (^finishedColorPicking)(TGPhotoPaintSettingsView *sender, TGPaintSwatch *swatch);
|
||||
|
||||
@property (nonatomic, copy) void (^eyedropperPressed)(void);
|
||||
@property (nonatomic, copy) void (^settingsPressed)(void);
|
||||
|
||||
@property (nonatomic, readonly) UIButton *settingsButton;
|
||||
|
||||
@property (nonatomic, strong) TGPaintSwatch *swatch;
|
||||
|
@ -14,6 +14,7 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f;
|
||||
@interface TGPhotoPaintSettingsView ()
|
||||
{
|
||||
TGPhotoPaintColorPicker *_colorPicker;
|
||||
TGModernButton *_eyedropperButton;
|
||||
TGModernButton *_settingsButton;
|
||||
TGPhotoPaintSettingsViewIcon _icon;
|
||||
|
||||
@ -54,7 +55,13 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f;
|
||||
};
|
||||
[self addSubview:_colorPicker];
|
||||
|
||||
_icon = TGPhotoPaintSettingsViewIconBrush;
|
||||
_icon = TGPhotoPaintSettingsViewIconBrushPen;
|
||||
|
||||
_eyedropperButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 44.0f, 44.0f)];
|
||||
_eyedropperButton.exclusiveTouch = true;
|
||||
[_eyedropperButton setImage:TGTintedImage([UIImage imageNamed:@"Editor/Eyedropper"], [UIColor whiteColor]) forState:UIControlStateNormal];
|
||||
[_eyedropperButton addTarget:self action:@selector(eyedropperButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:_eyedropperButton];
|
||||
|
||||
_settingsButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 44.0f, 44.0f)];
|
||||
_settingsButton.exclusiveTouch = true;
|
||||
@ -85,6 +92,12 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f;
|
||||
_colorPicker.orientation = interfaceOrientation;
|
||||
}
|
||||
|
||||
- (void)eyedropperButtonPressed
|
||||
{
|
||||
if (self.eyedropperPressed != nil)
|
||||
self.eyedropperPressed();
|
||||
}
|
||||
|
||||
- (void)settingsButtonPressed
|
||||
{
|
||||
if (self.settingsPressed != nil)
|
||||
@ -143,25 +156,35 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f;
|
||||
|
||||
- (UIImage *)_imageForIcon:(TGPhotoPaintSettingsViewIcon)icon highlighted:(bool)highlighted
|
||||
{
|
||||
UIColor *color = highlighted ? [TGPhotoEditorInterfaceAssets accentColor] : [UIColor whiteColor];
|
||||
UIImage *iconImage = nil;
|
||||
switch (icon)
|
||||
{
|
||||
case TGPhotoPaintSettingsViewIconBrush:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/Brush"], [UIColor whiteColor]);
|
||||
case TGPhotoPaintSettingsViewIconBrushPen:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/BrushSelectedPen"], color);
|
||||
break;
|
||||
|
||||
case TGPhotoPaintSettingsViewIconText:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/Font"], [UIColor whiteColor]);
|
||||
case TGPhotoPaintSettingsViewIconBrushMarker:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/BrushSelectedMarker"], color);
|
||||
break;
|
||||
case TGPhotoPaintSettingsViewIconBrushNeon:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/BrushSelectedNeon"], color);
|
||||
break;
|
||||
case TGPhotoPaintSettingsViewIconBrushArrow:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/BrushSelectedArrow"], color);
|
||||
break;
|
||||
case TGPhotoPaintSettingsViewIconTextRegular:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/TextSelectedRegular"], color);
|
||||
break;
|
||||
case TGPhotoPaintSettingsViewIconTextOutlined:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/TextSelectedOutlined"], color);
|
||||
break;
|
||||
case TGPhotoPaintSettingsViewIconTextFramed:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/TextSelectedFramed"], color);
|
||||
break;
|
||||
|
||||
case TGPhotoPaintSettingsViewIconMirror:
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/Flip"], [UIColor whiteColor]);
|
||||
iconImage = TGTintedImage([UIImage imageNamed:@"Editor/Flip"], color);
|
||||
break;
|
||||
}
|
||||
|
||||
if (highlighted)
|
||||
iconImage = TGTintedImage(iconImage, [TGPhotoEditorInterfaceAssets accentColor]);
|
||||
|
||||
return iconImage;
|
||||
}
|
||||
|
||||
@ -188,22 +211,26 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f;
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
CGFloat inset = 66.0f;
|
||||
CGFloat colorPickerHeight = 10.0f;
|
||||
if (self.frame.size.width > self.frame.size.height)
|
||||
{
|
||||
if ([_context currentSizeClass] == UIUserInterfaceSizeClassRegular)
|
||||
{
|
||||
_colorPicker.frame = CGRectMake(ceil((self.frame.size.width - TGPhotoPaintSettingsPadPickerWidth) / 2.0f), ceil((self.frame.size.height - 18.0f) / 2.0f), TGPhotoPaintSettingsPadPickerWidth, 18.0f);
|
||||
_colorPicker.frame = CGRectMake(ceil((self.frame.size.width - TGPhotoPaintSettingsPadPickerWidth) / 2.0f), ceil((self.frame.size.height - colorPickerHeight) / 2.0f), TGPhotoPaintSettingsPadPickerWidth, colorPickerHeight);
|
||||
_settingsButton.frame = CGRectMake(CGRectGetMaxX(_colorPicker.frame) + 11.0f, floor((self.frame.size.height - _settingsButton.frame.size.height) / 2.0f) + 1.0f, _settingsButton.frame.size.width, _settingsButton.frame.size.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
_colorPicker.frame = CGRectMake(23.0f, ceil((self.frame.size.height - 18.0f) / 2.0f), self.frame.size.width - 23.0f - 66.0f, 18.0f);
|
||||
_colorPicker.frame = CGRectMake(inset, ceil((self.frame.size.height - colorPickerHeight) / 2.0f), self.frame.size.width - inset - inset, colorPickerHeight);
|
||||
_eyedropperButton.frame = CGRectMake(10.0f, floor((self.frame.size.height - _eyedropperButton.frame.size.height) / 2.0f) + 1.0f, _eyedropperButton.frame.size.width, _eyedropperButton.frame.size.height);
|
||||
_settingsButton.frame = CGRectMake(self.frame.size.width - _settingsButton.frame.size.width - 10.0f, floor((self.frame.size.height - _settingsButton.frame.size.height) / 2.0f) + 1.0f, _settingsButton.frame.size.width, _settingsButton.frame.size.height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_colorPicker.frame = CGRectMake(ceil((self.frame.size.width - 18.0f) / 2.0f), 66.0f, 18.0f, self.frame.size.height - 23.0f - 66.0f);
|
||||
_colorPicker.frame = CGRectMake(ceil((self.frame.size.width - colorPickerHeight) / 2.0f), inset, colorPickerHeight, self.frame.size.height - inset - inset);
|
||||
_eyedropperButton.frame = CGRectMake(floor((self.frame.size.width - _eyedropperButton.frame.size.width) / 2.0f), self.frame.size.height - _eyedropperButton.frame.size.height - 10.0, _eyedropperButton.frame.size.width, _eyedropperButton.frame.size.height);
|
||||
_settingsButton.frame = CGRectMake(floor((self.frame.size.width - _settingsButton.frame.size.width) / 2.0f), 10.0f, _settingsButton.frame.size.width, _settingsButton.frame.size.height);
|
||||
}
|
||||
}
|
||||
|
@ -128,8 +128,8 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
|
||||
CGSize dimensions = CGSizeZero;
|
||||
if ([self.item isKindOfClass:[TGMediaAsset class]])
|
||||
dimensions = ((TGMediaAsset *)self.item).dimensions;
|
||||
else if ([self.item isKindOfClass:[TGCameraCapturedVideo class]])
|
||||
dimensions = [((TGCameraCapturedVideo *)self.item).avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject.naturalSize;
|
||||
// else if ([self.item isKindOfClass:[TGCameraCapturedVideo class]])
|
||||
// dimensions = [((TGCameraCapturedVideo *)self.item).avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject.naturalSize;
|
||||
|
||||
if (!CGSizeEqualToSize(dimensions, CGSizeZero))
|
||||
_quality.maximumValue = [TGMediaVideoConverter bestAvailablePresetForDimensions:dimensions] - 1;
|
||||
@ -641,7 +641,7 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
|
||||
|
||||
[self updateInfo];
|
||||
|
||||
SSignal *assetSignal = [self.item isKindOfClass:[TGMediaAsset class]] ? [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item] : [SSignal single:((TGCameraCapturedVideo *)self.item).avAsset];
|
||||
SSignal *assetSignal = [self.item isKindOfClass:[TGMediaAsset class]] ? [TGMediaAssetImageSignals avAssetForVideoAsset:(TGMediaAsset *)self.item] : ((TGCameraCapturedVideo *)self.item).avAsset;
|
||||
|
||||
if ([self.item isKindOfClass:[TGMediaAsset class]])
|
||||
[self _updateVideoDuration:((TGMediaAsset *)self.item).videoDuration hasAudio:true];
|
||||
|
@ -120,7 +120,11 @@ const CGFloat TGPhotoStickerSelectionViewHandleSide = 30.0f;
|
||||
|
||||
- (bool)precisePointInside:(CGPoint)point
|
||||
{
|
||||
return [_stickerView pointInside:[_stickerView convertPoint:point fromView:self] withEvent:nil];
|
||||
CGPoint imagePoint = [_stickerView convertPoint:point fromView:self];
|
||||
if (![_stickerView pointInside:[_stickerView convertPoint:point fromView:self] withEvent:nil])
|
||||
return false;
|
||||
|
||||
return [_stickerView isOpaqueAtPoint:imagePoint];
|
||||
}
|
||||
|
||||
- (void)mirror
|
||||
|
@ -184,7 +184,7 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
{
|
||||
_style = style;
|
||||
switch (_style) {
|
||||
case TGPhotoPaintTextEntityStyleClassic:
|
||||
case TGPhotoPaintTextEntityStyleRegular:
|
||||
_textView.layer.shadowColor = [[UIColor blackColor] CGColor];
|
||||
_textView.layer.shadowOffset = CGSizeMake(0.0f, 4.0f);
|
||||
_textView.layer.shadowOpacity = 0.4f;
|
||||
@ -206,7 +206,7 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
- (void)updateColor
|
||||
{
|
||||
switch (_style) {
|
||||
case TGPhotoPaintTextEntityStyleClassic:
|
||||
case TGPhotoPaintTextEntityStyleRegular:
|
||||
{
|
||||
_textView.textColor = _swatch.color;
|
||||
_textView.strokeColor = nil;
|
||||
@ -214,7 +214,7 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGPhotoPaintTextEntityStyleBorder:
|
||||
case TGPhotoPaintTextEntityStyleOutlined:
|
||||
{
|
||||
_textView.textColor = [UIColor whiteColor];
|
||||
_textView.strokeColor = _swatch.color;
|
||||
@ -222,7 +222,7 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGPhotoPaintTextEntityStyleFrame:
|
||||
case TGPhotoPaintTextEntityStyleFramed:
|
||||
{
|
||||
CGFloat lightness = 0.0f;
|
||||
CGFloat r = 0.0f;
|
||||
@ -646,8 +646,6 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
if (i == 0) {
|
||||
last = cur;
|
||||
} else if (i > 0 && fabs(CGRectGetMaxY(last) - CGRectGetMinY(cur)) < 10.0) {
|
||||
NSValue *lastValue = [self.rectArray objectAtIndex:i-1];
|
||||
last = lastValue.CGRectValue;
|
||||
CGPoint a = cur.origin;
|
||||
CGPoint b = CGPointMake(CGRectGetMaxX(cur), cur.origin.y);
|
||||
CGPoint c = CGPointMake(last.origin.x, CGRectGetMaxY(last));
|
||||
@ -690,6 +688,8 @@ const CGFloat TGPhotoTextSelectionViewHandleSide = 30.0f;
|
||||
[addPath addLineToPoint:CGPointMake(d.x + _radius, d.y)];
|
||||
[self.path appendPath:addPath];
|
||||
}
|
||||
|
||||
last = cur;
|
||||
}
|
||||
}
|
||||
[self.path fill];
|
||||
|
@ -8,9 +8,6 @@
|
||||
@property (nonatomic, copy) void (^fontChanged)(TGPhotoPaintFont *font);
|
||||
@property (nonatomic, copy) void (^styleChanged)(TGPhotoPaintTextEntityStyle style);
|
||||
|
||||
@property (nonatomic, strong) TGPhotoPaintFont *font;
|
||||
@property (nonatomic, assign) TGPhotoPaintTextEntityStyle style;
|
||||
|
||||
- (instancetype)initWithFonts:(NSArray *)fonts selectedFont:(TGPhotoPaintFont *)font selectedStyle:(TGPhotoPaintTextEntityStyle)selectedStyle;
|
||||
|
||||
@end
|
||||
|
@ -8,7 +8,7 @@
|
||||
#import <LegacyComponents/TGModernButton.h>
|
||||
#import "TGPhotoTextEntityView.h"
|
||||
|
||||
const CGFloat TGPhotoTextSettingsViewMargin = 19.0f;
|
||||
const CGFloat TGPhotoTextSettingsViewMargin = 10.0f;
|
||||
const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
|
||||
@interface TGPhotoTextSettingsView ()
|
||||
@ -17,11 +17,13 @@ const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
|
||||
UIInterfaceOrientation _interfaceOrientation;
|
||||
|
||||
UIImageView *_backgroundView;
|
||||
UIView *_wrapperView;
|
||||
UIView *_contentView;
|
||||
UIVisualEffectView *_effectView;
|
||||
|
||||
NSArray *_fontViews;
|
||||
NSArray *_fontIconViews;
|
||||
NSArray *_fontSeparatorViews;
|
||||
UIImageView *_selectedCheckView;
|
||||
}
|
||||
@end
|
||||
|
||||
@ -38,95 +40,91 @@ const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
|
||||
_interfaceOrientation = UIInterfaceOrientationPortrait;
|
||||
|
||||
_backgroundView = [[UIImageView alloc] init];
|
||||
_backgroundView.alpha = 0.98f;
|
||||
[self addSubview:_backgroundView];
|
||||
_wrapperView = [[UIView alloc] init];
|
||||
_wrapperView.clipsToBounds = true;
|
||||
_wrapperView.layer.cornerRadius = 12.0;
|
||||
[self addSubview:_wrapperView];
|
||||
|
||||
_effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
|
||||
_effectView.alpha = 0.0f;
|
||||
_effectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_wrapperView addSubview:_effectView];
|
||||
|
||||
_contentView = [[UIView alloc] init];
|
||||
_contentView.alpha = 0.0f;
|
||||
_contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[_wrapperView addSubview:_contentView];
|
||||
|
||||
NSMutableArray *fontViews = [[NSMutableArray alloc] init];
|
||||
NSMutableArray *fontIconViews = [[NSMutableArray alloc] init];
|
||||
NSMutableArray *separatorViews = [[NSMutableArray alloc] init];
|
||||
|
||||
UIFont *font = [UIFont boldSystemFontOfSize:18];
|
||||
UIFont *font = [UIFont systemFontOfSize:17];
|
||||
|
||||
TGModernButton *outlineButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, TGPhotoTextSettingsViewMargin, 0, 0)];
|
||||
outlineButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
outlineButton.titleLabel.font = font;
|
||||
outlineButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 44.0f, 0.0f, 0.0f);
|
||||
outlineButton.tag = TGPhotoPaintTextEntityStyleBorder;
|
||||
[outlineButton setTitle:@"" forState:UIControlStateNormal];
|
||||
[outlineButton setTitleColor:[UIColor clearColor]];
|
||||
[outlineButton addTarget:self action:@selector(styleValueChanged:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:outlineButton];
|
||||
[fontViews addObject:outlineButton];
|
||||
|
||||
TGPhotoTextView *textView = [[TGPhotoTextView alloc] init];
|
||||
textView.backgroundColor = [UIColor clearColor];
|
||||
textView.textColor = [UIColor whiteColor];
|
||||
textView.strokeWidth = 3.0f;
|
||||
textView.strokeColor = [UIColor blackColor];
|
||||
textView.strokeOffset = CGPointMake(0.0f, 0.5f);
|
||||
textView.font = font;
|
||||
textView.text = TGLocalized(@"Paint.Outlined");
|
||||
[textView sizeToFit];
|
||||
textView.frame = CGRectMake(39.0f, ceil((TGPhotoTextSettingsItemHeight - textView.frame.size.height) / 2.0f) - 1.0f, ceil(textView.frame.size.width), ceil(textView.frame.size.height + 0.5f));
|
||||
[outlineButton addSubview:textView];
|
||||
|
||||
UIView *separatorView = [[UIView alloc] init];
|
||||
separatorView.backgroundColor = UIColorRGB(0xd6d6da);
|
||||
[self addSubview:separatorView];
|
||||
[separatorViews addObject:separatorView];
|
||||
|
||||
TGModernButton *regularButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, TGPhotoTextSettingsViewMargin + TGPhotoTextSettingsItemHeight, 0, 0)];
|
||||
regularButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
regularButton.titleLabel.font = font;
|
||||
regularButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 44.0f, 0.0f, 0.0f);
|
||||
regularButton.tag = TGPhotoPaintTextEntityStyleClassic;
|
||||
[regularButton setTitle:TGLocalized(@"Paint.Regular") forState:UIControlStateNormal];
|
||||
[regularButton setTitleColor:[UIColor blackColor]];
|
||||
[regularButton addTarget:self action:@selector(styleValueChanged:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:regularButton];
|
||||
[fontViews addObject:regularButton];
|
||||
|
||||
separatorView = [[UIView alloc] init];
|
||||
separatorView.backgroundColor = UIColorRGB(0xd6d6da);
|
||||
[self addSubview:separatorView];
|
||||
[separatorViews addObject:separatorView];
|
||||
|
||||
TGModernButton *frameButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, TGPhotoTextSettingsViewMargin + TGPhotoTextSettingsItemHeight + TGPhotoTextSettingsItemHeight, 0, 0)];
|
||||
TGModernButton *frameButton = [[TGModernButton alloc] initWithFrame:CGRectZero];
|
||||
frameButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
frameButton.titleLabel.font = font;
|
||||
frameButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 44.0f, 0.0f, 0.0f);
|
||||
frameButton.tag = TGPhotoPaintTextEntityStyleFrame;
|
||||
[frameButton setTitle:@"" forState:UIControlStateNormal];
|
||||
[frameButton setTitleColor:[UIColor blackColor]];
|
||||
frameButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 16.0f, 0.0f, 0.0f);
|
||||
frameButton.tag = TGPhotoPaintTextEntityStyleFramed;
|
||||
[frameButton setTitle:TGLocalized(@"Paint.Framed") forState:UIControlStateNormal];
|
||||
[frameButton setTitleColor:[UIColor whiteColor]];
|
||||
[frameButton addTarget:self action:@selector(styleValueChanged:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:frameButton];
|
||||
[_contentView addSubview:frameButton];
|
||||
[fontViews addObject:frameButton];
|
||||
|
||||
textView = [[TGPhotoTextView alloc] init];
|
||||
textView.backgroundColor = [UIColor clearColor];
|
||||
textView.textColor = [UIColor whiteColor];
|
||||
textView.frameColor = [UIColor blackColor];
|
||||
textView.font = font;
|
||||
textView.text = TGLocalized(@"Paint.Framed");
|
||||
[textView sizeToFit];
|
||||
textView.frame = CGRectMake(39.0f, ceil((TGPhotoTextSettingsItemHeight - textView.frame.size.height) / 2.0f) - 1.0f, ceil(textView.frame.size.width), ceil(textView.frame.size.height + 0.5f));
|
||||
[frameButton addSubview:textView];
|
||||
UIImageView *iconView = [[UIImageView alloc] initWithImage:TGTintedImage([UIImage imageNamed:@"Editor/TextFramed"], [UIColor whiteColor])];
|
||||
[frameButton addSubview:iconView];
|
||||
[fontIconViews addObject:iconView];
|
||||
|
||||
TGModernButton *outlineButton = [[TGModernButton alloc] initWithFrame:CGRectZero];
|
||||
outlineButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
outlineButton.titleLabel.font = font;
|
||||
outlineButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 16.0f, 0.0f, 0.0f);
|
||||
outlineButton.tag = TGPhotoPaintTextEntityStyleOutlined;
|
||||
[outlineButton setTitle:TGLocalized(@"Paint.Outlined") forState:UIControlStateNormal];
|
||||
[outlineButton setTitleColor:[UIColor whiteColor]];
|
||||
[outlineButton addTarget:self action:@selector(styleValueChanged:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_contentView addSubview:outlineButton];
|
||||
[fontViews addObject:outlineButton];
|
||||
|
||||
iconView = [[UIImageView alloc] initWithImage:TGTintedImage([UIImage imageNamed:@"Editor/TextOutlined"], [UIColor whiteColor])];
|
||||
[outlineButton addSubview:iconView];
|
||||
[fontIconViews addObject:iconView];
|
||||
|
||||
UIView *separatorView = [[UIView alloc] init];
|
||||
separatorView.backgroundColor = UIColorRGBA(0xffffff, 0.2);
|
||||
[_contentView addSubview:separatorView];
|
||||
[separatorViews addObject:separatorView];
|
||||
|
||||
TGModernButton *regularButton = [[TGModernButton alloc] initWithFrame:CGRectZero];
|
||||
regularButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
regularButton.titleLabel.font = font;
|
||||
regularButton.contentEdgeInsets = UIEdgeInsetsMake(0.0f, 16.0f, 0.0f, 0.0f);
|
||||
regularButton.tag = TGPhotoPaintTextEntityStyleRegular;
|
||||
[regularButton setTitle:TGLocalized(@"Paint.Regular") forState:UIControlStateNormal];
|
||||
[regularButton setTitleColor:[UIColor whiteColor]];
|
||||
[regularButton addTarget:self action:@selector(styleValueChanged:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_contentView addSubview:regularButton];
|
||||
[fontViews addObject:regularButton];
|
||||
|
||||
iconView = [[UIImageView alloc] initWithImage:TGTintedImage([UIImage imageNamed:@"Editor/TextRegular"], [UIColor whiteColor])];
|
||||
[regularButton addSubview:iconView];
|
||||
[fontIconViews addObject:iconView];
|
||||
|
||||
separatorView = [[UIView alloc] init];
|
||||
separatorView.backgroundColor = UIColorRGBA(0xffffff, 0.2);
|
||||
[_contentView addSubview:separatorView];
|
||||
[separatorViews addObject:separatorView];
|
||||
|
||||
_fontViews = fontViews;
|
||||
_fontIconViews = fontIconViews;
|
||||
_fontSeparatorViews = separatorViews;
|
||||
|
||||
_selectedCheckView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"PaintCheck")];
|
||||
_selectedCheckView.frame = CGRectMake(15.0f, 16.0f, _selectedCheckView.frame.size.width, _selectedCheckView.frame.size.height);
|
||||
|
||||
[self setStyle:selectedStyle];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)fontButtonPressed:(TGModernButton *)sender
|
||||
{
|
||||
[sender addSubview:_selectedCheckView];
|
||||
|
||||
if (self.fontChanged != nil)
|
||||
self.fontChanged(_fonts[sender.tag]);
|
||||
}
|
||||
@ -139,28 +137,22 @@ const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
|
||||
- (void)present
|
||||
{
|
||||
self.alpha = 0.0f;
|
||||
|
||||
self.layer.rasterizationScale = TGScreenScaling();
|
||||
self.layer.shouldRasterize = true;
|
||||
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
[UIView animateWithDuration:0.25 animations:^
|
||||
{
|
||||
self.alpha = 1.0f;
|
||||
_effectView.alpha = 1.0f;
|
||||
_contentView.alpha = 1.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
self.layer.shouldRasterize = false;
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismissWithCompletion:(void (^)(void))completion
|
||||
{
|
||||
self.layer.rasterizationScale = TGScreenScaling();
|
||||
self.layer.shouldRasterize = true;
|
||||
|
||||
[UIView animateWithDuration:0.15 animations:^
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
self.alpha = 0.0f;
|
||||
_effectView.alpha = 0.0f;
|
||||
_contentView.alpha = 0.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
if (completion != nil)
|
||||
@ -168,81 +160,38 @@ const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
}];
|
||||
}
|
||||
|
||||
- (TGPhotoPaintTextEntityStyle)style
|
||||
{
|
||||
return (TGPhotoPaintTextEntityStyle)_selectedCheckView.superview.tag;
|
||||
}
|
||||
|
||||
- (void)setStyle:(TGPhotoPaintTextEntityStyle)style
|
||||
{
|
||||
[_fontViews[style] addSubview:_selectedCheckView];
|
||||
}
|
||||
|
||||
- (NSString *)font
|
||||
{
|
||||
return _fonts[_selectedCheckView.superview.tag];
|
||||
}
|
||||
|
||||
- (void)setFont:(TGPhotoPaintFont *)__unused font
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)__unused size
|
||||
{
|
||||
return CGSizeMake(256, _fontViews.count * TGPhotoTextSettingsItemHeight + TGPhotoTextSettingsViewMargin * 2);
|
||||
return CGSizeMake(220, _fontViews.count * TGPhotoTextSettingsItemHeight + TGPhotoTextSettingsViewMargin * 2);
|
||||
}
|
||||
|
||||
- (void)setInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
_interfaceOrientation = interfaceOrientation;
|
||||
|
||||
switch (self.interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView landscapeLeftBackgroundImage];
|
||||
}
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView landscapeRightBackgroundImage];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
_backgroundView.image = [TGPhotoPaintSettingsView portraitBackgroundImage];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
CGFloat arrowSize = 0.0f;
|
||||
switch (self.interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
{
|
||||
_backgroundView.image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupLandscapeLeftBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)];
|
||||
_backgroundView.frame = CGRectMake(TGPhotoTextSettingsViewMargin - 13.0f, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2 + 13.0f, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoTextSettingsViewMargin - arrowSize, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2 + arrowSize, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
{
|
||||
_backgroundView.image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupLandscapeRightBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)];
|
||||
_backgroundView.frame = CGRectMake(TGPhotoTextSettingsViewMargin, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2 + 13.0f, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoTextSettingsViewMargin, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2 + arrowSize, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
_backgroundView.image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupPortraitBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)];
|
||||
_backgroundView.frame = CGRectMake(TGPhotoTextSettingsViewMargin, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2 + 13.0f);
|
||||
_wrapperView.frame = CGRectMake(TGPhotoTextSettingsViewMargin, TGPhotoTextSettingsViewMargin, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2, self.frame.size.height - TGPhotoTextSettingsViewMargin * 2 + arrowSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -251,13 +200,17 @@ const CGFloat TGPhotoTextSettingsItemHeight = 44.0f;
|
||||
|
||||
[_fontViews enumerateObjectsUsingBlock:^(TGModernButton *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(TGPhotoTextSettingsViewMargin, TGPhotoTextSettingsViewMargin + TGPhotoTextSettingsItemHeight * index, self.frame.size.width - TGPhotoTextSettingsViewMargin * 2, TGPhotoTextSettingsItemHeight);
|
||||
|
||||
view.frame = CGRectMake(0.0, TGPhotoTextSettingsItemHeight * index, _contentView.frame.size.width, TGPhotoTextSettingsItemHeight);
|
||||
}];
|
||||
|
||||
[_fontIconViews enumerateObjectsUsingBlock:^(UIImageView *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(_contentView.frame.size.width - 42.0f, (TGPhotoTextSettingsItemHeight - view.frame.size.height) / 2.0, view.frame.size.width, view.frame.size.height);
|
||||
}];
|
||||
|
||||
[_fontSeparatorViews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
view.frame = CGRectMake(TGPhotoTextSettingsViewMargin + 44.0f, TGPhotoTextSettingsViewMargin + TGPhotoTextSettingsItemHeight * (index + 1), self.frame.size.width - TGPhotoTextSettingsViewMargin * 2 - 44.0f, thickness);
|
||||
view.frame = CGRectMake(0.0, TGPhotoTextSettingsItemHeight * (index + 1), _contentView.frame.size.width, thickness);
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:@[galleryItem] focusItem:galleryItem selectionContext:nil editingContext:editingContext hasCaptions:true allowCaptionEntities:true hasTimer:false onlyCrop:false inhibitDocumentCaptions:false hasSelectionPanel:false hasCamera:false recipientName:recipientName];
|
||||
model.controller = galleryController;
|
||||
model.stickersContext = stickersContext;
|
||||
//model.suggestionContext = self.suggestionContext;
|
||||
|
||||
model.willFinishEditingItem = ^(id<TGMediaEditableItem> editableItem, id<TGMediaEditAdjustments> adjustments, id representation, bool hasChanges)
|
||||
|
@ -91,7 +91,7 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
|
||||
} else if ([dict[@"type"] isEqualToString:@"text"]) {
|
||||
UIImage *renderImage = [[UIImage alloc] initWithData:dict[@"data"]];
|
||||
if (renderImage != nil) {
|
||||
TGPhotoPaintTextEntity *entity = [[TGPhotoPaintTextEntity alloc] initWithText:nil font:nil swatch:nil baseFontSize:0.0 maxWidth:0.0 style:TGPhotoPaintTextEntityStyleClassic];
|
||||
TGPhotoPaintTextEntity *entity = [[TGPhotoPaintTextEntity alloc] initWithText:nil font:nil swatch:nil baseFontSize:0.0 maxWidth:0.0 style:TGPhotoPaintTextEntityStyleRegular];
|
||||
entity.uuid = [dict[@"uuid"] integerValue];
|
||||
entity.position = [dict[@"position"] CGPointValue];
|
||||
entity.scale = [dict[@"scale"] floatValue];
|
||||
|
Loading…
x
Reference in New Issue
Block a user