mirror of
https://github.com/danog/Telegram.git
synced 2024-12-03 09:57:46 +01:00
129 lines
4.1 KiB
Objective-C
129 lines
4.1 KiB
Objective-C
#import "TGHistogramView.h"
|
|
#import "PGPhotoHistogram.h"
|
|
#import "TGPhotoEditorCurvesToolView.h"
|
|
|
|
const NSUInteger TGHistogramGranularity = 20;
|
|
|
|
@interface CAAnimatedShapeLayer : CAShapeLayer
|
|
|
|
@end
|
|
|
|
@implementation CAAnimatedShapeLayer
|
|
|
|
- (id<CAAction>)actionForKey:(NSString *)event
|
|
{
|
|
if ([event isEqualToString:@"path"] || [event isEqualToString:@"fillColor"])
|
|
{
|
|
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
|
|
animation.duration = [CATransaction animationDuration];
|
|
animation.timingFunction = [CATransaction animationTimingFunction];
|
|
return animation;
|
|
}
|
|
|
|
return [super actionForKey:event];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGHistogramView
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:frame];
|
|
if (self != nil)
|
|
{
|
|
[self shapeLayer].fillColor = [UIColor whiteColor].CGColor;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (CAShapeLayer *)shapeLayer
|
|
{
|
|
return (CAShapeLayer *)self.layer;
|
|
}
|
|
|
|
+ (Class)layerClass
|
|
{
|
|
return [CAAnimatedShapeLayer class];
|
|
}
|
|
|
|
- (void)setHistogram:(PGPhotoHistogram *)histogram type:(PGCurvesType)type animated:(bool)animated
|
|
{
|
|
void (^changeBlock)(void) = ^
|
|
{
|
|
[self shapeLayer].path = [self _bezierPathForHistogramBins:[histogram histogramBinsForType:type]].CGPath;
|
|
[self shapeLayer].fillColor = [TGPhotoEditorCurvesToolView colorForCurveType:type].CGColor;
|
|
};
|
|
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.25f animations:changeBlock];
|
|
}
|
|
else
|
|
{
|
|
changeBlock();
|
|
}
|
|
}
|
|
|
|
- (CGPoint)_viewPointWithValue:(CGFloat)value index:(NSInteger)index step:(CGFloat)step actualSize:(CGSize)actualSize
|
|
{
|
|
return CGPointMake(index * step, (1.0 - value) * actualSize.height);
|
|
}
|
|
|
|
- (UIBezierPath *)_bezierPathForHistogramBins:(PGPhotoHistogramBins *)histogramBins
|
|
{
|
|
UIBezierPath *path = [[UIBezierPath alloc] init];
|
|
|
|
if (histogramBins == nil)
|
|
return path;
|
|
|
|
CGSize actualSize = self.frame.size;
|
|
if (self.isLandscape)
|
|
actualSize = CGSizeMake(actualSize.height, actualSize.width);
|
|
|
|
CGFloat firstValue = [histogramBins[0] floatValue];
|
|
[path moveToPoint:CGPointMake(-1, actualSize.height)];
|
|
[path addLineToPoint:CGPointMake(-1, (1 - firstValue) * actualSize.height)];
|
|
|
|
CGFloat xStep = actualSize.width / 255.0f;
|
|
|
|
for (NSUInteger index = 1; index < histogramBins.count - 2; index++)
|
|
{
|
|
CGPoint point0 = [self _viewPointWithValue:[histogramBins[index - 1] floatValue] index:index - 1 step:xStep actualSize:actualSize];
|
|
CGPoint point1 = [self _viewPointWithValue:[histogramBins[index] floatValue] index:index step:xStep actualSize:actualSize];
|
|
CGPoint point2 = [self _viewPointWithValue:[histogramBins[index + 1] floatValue] index:index + 1 step:xStep actualSize:actualSize];
|
|
CGPoint point3 = [self _viewPointWithValue:[histogramBins[index + 2] floatValue] index:index + 2 step:xStep actualSize:actualSize];
|
|
|
|
for (NSUInteger i = 1; i < TGHistogramGranularity; i++)
|
|
{
|
|
CGFloat t = (CGFloat)i * (1.0f / (CGFloat)TGHistogramGranularity);
|
|
CGFloat tt = t * t;
|
|
CGFloat ttt = tt * t;
|
|
|
|
CGPoint pi =
|
|
{
|
|
0.5 * (2 * point1.x + (point2.x - point0.x) * t + (2 * point0.x - 5 * point1.x + 4 * point2.x - point3.x) * tt + (3 * point1.x - point0.x - 3 * point2.x + point3.x) * ttt),
|
|
0.5 * (2 * point1.y + (point2.y - point0.y) * t + (2 * point0.y - 5 * point1.y + 4 * point2.y - point3.y) * tt + (3 * point1.y - point0.y - 3 * point2.y + point3.y) * ttt)
|
|
};
|
|
|
|
pi.y = MAX(0, MIN(actualSize.height, pi.y));
|
|
|
|
if (pi.x > point0.x)
|
|
[path addLineToPoint:pi];
|
|
}
|
|
|
|
[path addLineToPoint:point2];
|
|
}
|
|
|
|
CGFloat lastValue = [histogramBins[histogramBins.count - 1] floatValue];
|
|
[path addLineToPoint:CGPointMake(actualSize.width + 1, (1 - lastValue) * actualSize.height)];
|
|
|
|
[path addLineToPoint:CGPointMake(actualSize.width+ 1, actualSize.height)];
|
|
|
|
[path closePath];
|
|
|
|
return path;
|
|
}
|
|
|
|
@end
|