From 764722d0366346dc435aa906abdd25655e3b0769 Mon Sep 17 00:00:00 2001
From: 单军华 <WindShan@danjunhuas-MacBook-Pro.local>
Date: Fri, 03 Mar 2017 09:54:19 +0800
Subject: [PATCH] 图形绘制demo

---
 PNChartdemo/PNChartdemo/PNChart/PNChartDelegate.h                                                                    |   33 
 PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.m                                                            |  234 +
 PNChartdemo/PNChart/PNScatterChart.m                                                                                 |  445 ++
 PNChartdemo/PNChartdemo/PNChart/PNScatterChart.h                                                                     |   69 
 PNChartdemo/PNChart/PNPieChart.h                                                                                     |   68 
 PNChartdemo/PNChart/PNChart.h                                                                                        |   22 
 PNChartdemo/PNChart/PNScatterChart.h                                                                                 |   69 
 PNChartdemo/PNChart/PNLineChart.m                                                                                    | 1285 ++++++
 PNChartdemo/PNChart/PNLineChartDataItem.m                                                                            |   38 
 PNChartdemo/PNChart/PNPieChart.m                                                                                     |  508 ++
 PNChartdemo/PNChartdemo/PCChartViewController.m                                                                      |  490 ++
 PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.m                                                             |   37 
 PNChartdemo/PNChart/PNLineChartDataItem.h                                                                            |   17 
 PNChartdemo/PNChart/PNLineChart.h                                                                                    |  110 
 PNChartdemo/PNChart/PNScatterChartData.h                                                                             |   38 
 PNChartdemo/PNChartdemo/PCChartViewController.h                                                                      |   38 
 PNChartdemo/PNChartdemo/PNChart/PNLineChart.h                                                                        |  110 
 PNChartdemo/PNChart/PNBar.h                                                                                          |   37 
 PNChartdemo/PNChartdemo/ViewController.m                                                                             |    4 
 PNChartdemo/PNChartdemo/AppDelegate.m                                                                                |    4 
 PNChartdemo/PNChart/PNBar.m                                                                                          |  288 +
 PNChartdemo/PNChartdemo/ViewController.h                                                                             |    4 
 PNChartdemo/PNChartdemo/AppDelegate.h                                                                                |    4 
 PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.h                                                            |   36 
 PNChartdemo/PNChart/PNRadarChart.h                                                                                   |   52 
 PNChartdemo/PNChartdemo/Base.lproj/Main.storyboard                                                                   |  300 +
 PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.h                                                                 |   25 
 PNChartdemo/PNChart/PNCircleChart.m                                                                                  |  267 +
 PNChartdemo/PNChart/PNBarChart.m                                                                                     |  459 ++
 PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/PNChartdemo.xcscheme                     |   91 
 PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.h                                                             |   19 
 PNChartdemo/PNChartdemo/PNChart/PNColor.h                                                                            |   53 
 PNChartdemo/PNChartdemo/PNChart/PNPieChart.h                                                                         |   68 
 PNChartdemo/PNChart/PNCircleChart.h                                                                                  |   74 
 PNChartdemo/PNChartdemo/PNChart/PNColor.m                                                                            |   29 
 PNChartdemo/PNChartdemo/PNChart/PNChartLabel.m                                                                       |   32 
 PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.m                                                                 |   38 
 PNChartdemo/PNChartdemo/PNChart/PNPieChart.m                                                                         |  508 ++
 PNChartdemo/PNChart/PNGenericChart.m                                                                                 |   54 
 PNChartdemo/PNChartdemo/PNChart/PNScatterChart.m                                                                     |  445 ++
 PNChartdemo/PNChartdemo/PNChart/PNChartLabel.h                                                                       |   13 
 PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.h                                                                |   17 
 PNChartdemo/PNChart/PNRadarChart.m                                                                                   |  373 +
 PNChartdemo/PNChart/PNGenericChart.h                                                                                 |   48 
 PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist               |   55 
 PNChartdemo/PNChartdemo/PNChart/PNBarChart.h                                                                         |  123 
 PNChartdemo/PNChartdemo/PNChart/PNGenericChart.m                                                                     |   54 
 PNChartdemo/PNChart/PNColor.h                                                                                        |   53 
 PNChartdemo/PNChartdemo/PNChart/PNBarChart.m                                                                         |  459 ++
 PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.m                                                                |   38 
 PNChartdemo/PNChart/PNColor.m                                                                                        |   29 
 PNChartdemo/PNChartdemo/PNChart/PNChart.h                                                                            |   22 
 PNChartdemo/PNChartdemo.xcodeproj/project.pbxproj                                                                    |  479 ++
 PNChartdemo/PNChartdemo/PNChart/PNGenericChart.h                                                                     |   48 
 PNChartdemo/PNChart/PNPieChartDataItem.m                                                                             |   38 
 PNChartdemo/PNChartdemo/Info.plist                                                                                   |    0 
 PNChartdemo/PNChart/PNBarChart.h                                                                                     |  123 
 PNChartdemo/PNChart/PNPieChartDataItem.h                                                                             |   25 
 PNChartdemo/PNChartdemo/PCChartsTableViewController.h                                                                |   13 
 PNChartdemo/PNChartdemo/PNChartDemo-Prefix.pch                                                                       |   16 
 PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist                 |    4 
 PNChartdemo/PNChartdemo/PCChartsTableViewController.m                                                                |   56 
 PNChartdemo/PNChartdemo/PNChart/PNRadarChart.h                                                                       |   52 
 PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata                                       |    2 
 PNChartdemo/PNChartdemo/PNChart/PNCircleChart.h                                                                      |   74 
 PNChartdemo/PNChart/PNRadarChartDataItem.m                                                                           |   29 
 PNChartdemo/PNChartdemo/Base.lproj/LaunchScreen.storyboard                                                           |    0 
 PNChartdemo/PNChart/PNChartLabel.m                                                                                   |   32 
 PNChartdemo/PNChartdemo/PNChart/PNRadarChart.m                                                                       |  373 +
 PNChartdemo/PNChart/PNRadarChartDataItem.h                                                                           |   19 
 PNChartdemo/PNChartdemo/PNChart/PNCircleChart.m                                                                      |  267 +
 PNChartdemo/PNChart/PNChartLabel.h                                                                                   |   13 
 PNChartdemo/PNChartdemo/PNChart/PNLineChart.m                                                                        | 1284 ++++++
 PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate |    0 
 PNChartdemo/PNChart/PNChartDelegate.h                                                                                |   33 
 PNChartdemo/PNChart/PNScatterChartData.m                                                                             |   31 
 PNChartdemo/PNChartdemo/PNChart/PNBar.h                                                                              |   37 
 PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.m                                                                 |   31 
 /dev/null                                                                                                            |  114 
 PNChartdemo/PNChart/PNLineChartData.m                                                                                |   54 
 PNChartdemo/PNChart/PNScatterChartDataItem.h                                                                         |   19 
 PNChartdemo/PNChartdemo/main.m                                                                                       |    4 
 PNChartdemo/PNChartdemo/PNChart/PNBar.m                                                                              |  288 +
 PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.m                                                               |   29 
 PNChartdemo/PNChart/PNScatterChartDataItem.m                                                                         |   37 
 PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.h                                                                 |   38 
 PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.h                                                               |   19 
 PNChartdemo/PNChartdemo/Assets.xcassets/AppIcon.appiconset/Contents.json                                             |    0 
 PNChartdemo/PNChartdemo/PNChart/PNLineChartData.m                                                                    |   54 
 PNChartdemo/PNChartdemo/PNChart/PNLineChartData.h                                                                    |   61 
 PNChartdemo/PNChart/PNLineChartData.h                                                                                |   61 
 91 files changed, 11,516 insertions(+), 127 deletions(-)

diff --git a/PNChartdemo/PNChart/PNBar.h b/PNChartdemo/PNChart/PNBar.h
new file mode 100755
index 0000000..68e6b0b
--- /dev/null
+++ b/PNChartdemo/PNChart/PNBar.h
@@ -0,0 +1,37 @@
+//
+//  PNBar.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+
+@interface PNBar : UIView
+
+
+- (void)rollBack;
+
+@property (nonatomic) float grade;
+@property (nonatomic) float maxDivisor;
+
+@property (nonatomic) CAShapeLayer *chartLine;
+@property (nonatomic) UIColor *barColor;
+@property (nonatomic) UIColor *barColorGradientStart;
+@property (nonatomic) CGFloat barRadius;
+@property (nonatomic) CAShapeLayer *gradientMask;
+
+@property (nonatomic) CAShapeLayer *gradeLayer;
+@property (nonatomic) CATextLayer* textLayer;
+
+/** Text color for all bars in the chart. */
+@property (nonatomic) UIColor * labelTextColor;
+
+@property (nonatomic, assign) BOOL isNegative;          //!< ���������������
+@property (nonatomic, assign) BOOL isShowNumber;        //!< ������������numbers
+
+/** Display the bar with or without animation. Default is YES. **/
+@property (nonatomic) BOOL displayAnimated;
+@end
diff --git a/PNChartdemo/PNChart/PNBar.m b/PNChartdemo/PNChart/PNBar.m
new file mode 100755
index 0000000..8ea5fc9
--- /dev/null
+++ b/PNChartdemo/PNChart/PNBar.m
@@ -0,0 +1,288 @@
+//
+//  PNBar.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNBar.h"
+#import "PNColor.h"
+#import <CoreText/CoreText.h>
+
+@interface PNBar ()
+
+@property (nonatomic) float copyGrade;
+
+@end
+
+@implementation PNBar
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        _chartLine              = [CAShapeLayer layer];
+        _chartLine.lineCap      = kCALineCapButt;
+        _chartLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartLine.lineWidth    = self.frame.size.width;
+        _chartLine.strokeEnd    = 0.0;
+        self.clipsToBounds      = YES;
+        [self.layer addSublayer:_chartLine];
+        self.barRadius = 2.0;
+    }
+
+    return self;
+}
+
+-(void)setBarRadius:(CGFloat)barRadius
+{
+    _barRadius = barRadius;
+    self.layer.cornerRadius = _barRadius;
+}
+
+
+- (void)setGrade:(float)grade
+{
+    _copyGrade = grade;
+    CGFloat startPosY = (1 - grade) * self.frame.size.height;
+
+    UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+    [progressline moveToPoint:CGPointMake(self.frame.size.width / 2.0, self.frame.size.height)];
+    [progressline addLineToPoint:CGPointMake(self.frame.size.width / 2.0, startPosY)];
+
+    [progressline setLineWidth:1.0];
+    [progressline setLineCapStyle:kCGLineCapSquare];
+    [self addAnimationIfNeededWithProgressLine:progressline];
+
+
+    if (_barColor) {
+        _chartLine.strokeColor = [_barColor CGColor];
+    }
+    else {
+        _chartLine.strokeColor = [PNGreen CGColor];
+    }
+
+    if (_grade) {
+        
+        _chartLine.path = progressline.CGPath;
+        
+        if (_barColorGradientStart) {
+            
+            // Add gradient
+            self.gradientMask.path = progressline.CGPath;
+  
+            CABasicAnimation* opacityAnimation = [self fadeAnimation];
+            [self.textLayer addAnimation:opacityAnimation forKey:nil];
+
+        }
+        
+    }else{
+        _chartLine.strokeEnd = 1.0;
+        
+        _chartLine.path = progressline.CGPath;
+        // Check if user wants to add a gradient from the start color to the bar color
+        if (_barColorGradientStart) {
+            
+            // Add gradient
+            self.gradientMask = [CAShapeLayer layer];
+            self.gradientMask.fillColor = [[UIColor clearColor] CGColor];
+            self.gradientMask.strokeColor = [[UIColor blackColor] CGColor];
+            self.gradientMask.lineWidth    = self.frame.size.width;
+            self.gradientMask.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
+            self.gradientMask.path = progressline.CGPath;
+            
+            CAGradientLayer *gradientLayer = [CAGradientLayer layer];
+            gradientLayer.startPoint = CGPointMake(0.0,0.0);
+            gradientLayer.endPoint = CGPointMake(1.0 ,0.0);
+            gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
+            UIColor *middleColor = [UIColor colorWithWhite:255/255 alpha:0.8];
+            NSArray *colors = @[
+                                (__bridge id)self.barColor.CGColor,
+                                (__bridge id)middleColor.CGColor,
+                                (__bridge id)self.barColor.CGColor
+                                ];
+            gradientLayer.colors = colors;
+            
+            [gradientLayer setMask:self.gradientMask];
+            
+            [_chartLine addSublayer:gradientLayer];
+            
+            self.gradientMask.strokeEnd = 1.0;
+
+            CABasicAnimation* opacityAnimation = [self fadeAnimation];
+            [self.textLayer addAnimation:opacityAnimation forKey:nil];
+        }
+    }
+    
+    _grade = grade;
+
+}
+
+
+- (void)rollBack
+{
+    [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations: ^{
+        _chartLine.strokeColor = [UIColor clearColor].CGColor;
+    } completion:nil];
+}
+
+- (void)setBarColorGradientStart:(UIColor *)barColorGradientStart
+{
+    // Set gradient color, remove any existing sublayer first
+    for (CALayer *sublayer in [_chartLine sublayers]) {
+        [sublayer removeFromSuperlayer];
+    }
+    _barColorGradientStart = barColorGradientStart;
+
+    [self setGrade:_grade];
+
+}
+
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect
+{
+    CGContextRef context = UIGraphicsGetCurrentContext();
+
+    CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
+    CGContextFillRect(context, rect);
+}
+
+
+// add number display on the top of bar
+-(CGPathRef)gradePath:(CGRect)rect
+{
+    return nil;
+}
+
+-(CATextLayer*)textLayer
+{
+    if (!_textLayer) {
+        _textLayer = [[CATextLayer alloc]init];
+        [_textLayer setString:@"0"];
+        [_textLayer setAlignmentMode:kCAAlignmentCenter];
+        [_textLayer setForegroundColor:[_labelTextColor CGColor]];
+       _textLayer.hidden = YES;
+
+    }
+
+    return _textLayer;
+}
+
+- (void) setLabelTextColor:(UIColor *)labelTextColor {
+    _labelTextColor = labelTextColor;
+    [_textLayer setForegroundColor:[_labelTextColor CGColor]];
+}
+
+-(void)setGradeFrame:(CGFloat)grade startPosY:(CGFloat)startPosY
+{
+    CGFloat textheigt = self.bounds.size.height*self.grade;
+  
+    CGFloat topSpace = self.bounds.size.height * (1-self.grade);
+    CGFloat textWidth = self.bounds.size.width;
+  
+    [_chartLine addSublayer:self.textLayer];
+    [self.textLayer setFontSize:18.0];
+  
+    [self.textLayer setString:[[NSString alloc]initWithFormat:@"%0.f",grade*self.maxDivisor]];
+  
+    CGSize size = CGSizeMake(320,2000); //������������������������
+    NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]};
+    size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
+    float verticalY ;
+  
+    if (size.height>=textheigt) {
+      
+      verticalY = topSpace - size.height;
+    } else {
+      verticalY = topSpace +  (textheigt-size.height)/2.0;
+    }
+  
+    [self.textLayer setFrame:CGRectMake((textWidth-size.width)/2.0,verticalY, size.width,size.height)];
+    self.textLayer.contentsScale = [UIScreen mainScreen].scale;
+
+}
+
+- (void)setIsShowNumber:(BOOL)isShowNumber{
+  if (isShowNumber) {
+    self.textLayer.hidden = NO;
+    [self setGradeFrame:_copyGrade startPosY:0];
+  }else{
+    self.textLayer.hidden = YES;
+  }
+}
+- (void)setIsNegative:(BOOL)isNegative{
+  if (isNegative) {
+    [self.textLayer setString:[[NSString alloc]initWithFormat:@"- %1.f",_grade*self.maxDivisor]];
+    
+    CGSize size = CGSizeMake(320,2000); //������������������������
+    NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]};
+    size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
+    CGRect frame = self.textLayer.frame;
+    frame.origin.x = (self.bounds.size.width - size.width)/2.0;
+    frame.size = size;
+    self.textLayer.frame = frame;
+      
+    [self addRotationAnimationIfNeeded];
+  }
+}
+
+-(CABasicAnimation*)fadeAnimation
+{
+    CABasicAnimation* fadeAnimation = nil;
+    if (self.displayAnimated) {
+        fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeAnimation.fromValue = [NSNumber numberWithFloat:0.0];
+        fadeAnimation.toValue = [NSNumber numberWithFloat:1.0];
+        fadeAnimation.duration = 2.0;
+    }
+    return fadeAnimation;
+}
+
+-(void)addAnimationIfNeededWithProgressLine:(UIBezierPath *)progressline
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = nil;
+        
+        if (_grade) {
+            pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+            pathAnimation.fromValue = (id)_chartLine.path;
+            pathAnimation.toValue = (id)[progressline CGPath];
+            pathAnimation.duration = 0.5f;
+            pathAnimation.autoreverses = NO;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            [_chartLine addAnimation:pathAnimation forKey:@"animationKey"];
+        }
+        else {
+            pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+            pathAnimation.duration = 1.0;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            pathAnimation.fromValue = @0.0f;
+            pathAnimation.toValue = @1.0f;
+            [_chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+        
+        [self.gradientMask addAnimation:pathAnimation forKey:@"animationKey"];
+    }
+}
+
+- (void)addRotationAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation* rotationAnimation;
+        rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+        rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI];
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        rotationAnimation.duration = 0.1;
+        rotationAnimation.repeatCount = 0;//������������������������������������
+        rotationAnimation.cumulative = NO;
+        rotationAnimation.removedOnCompletion = NO;
+        rotationAnimation.fillMode = kCAFillModeForwards;
+        [self.textLayer addAnimation:rotationAnimation forKey:@"Rotation"];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNBarChart.h b/PNChartdemo/PNChart/PNBarChart.h
new file mode 100755
index 0000000..e628c08
--- /dev/null
+++ b/PNChartdemo/PNChart/PNBarChart.h
@@ -0,0 +1,123 @@
+//
+//  PNBarChart.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNGenericChart.h"
+#import "PNChartDelegate.h"
+#import "PNBar.h"
+
+#define kXLabelMargin 15
+#define kYLabelMargin 15
+#define kYLabelHeight 11
+#define kXLabelHeight 20
+
+typedef NSString *(^PNYLabelFormatter)(CGFloat yLabelValue);
+
+@interface PNBarChart : PNGenericChart
+
+/**
+ * Draws the chart in an animated fashion.
+ */
+- (void)strokeChart;
+
+@property (nonatomic) NSArray *xLabels;
+@property (nonatomic) NSArray *yLabels;
+@property (nonatomic) NSArray *yValues;
+
+@property (nonatomic) NSMutableArray * bars;
+
+@property (nonatomic) CGFloat xLabelWidth;
+@property (nonatomic) float yValueMax;
+@property (nonatomic) UIColor *strokeColor;
+@property (nonatomic) NSArray *strokeColors;
+
+
+/** Update Values. */
+- (void)updateChartData:(NSArray *)data;
+
+/** Changes chart margin. */
+@property (nonatomic) CGFloat yChartLabelWidth;
+
+/** Formats the ylabel text. */
+@property (copy) PNYLabelFormatter yLabelFormatter;
+
+/** Prefix to y label values, none if unset. */
+@property (nonatomic) NSString *yLabelPrefix;
+
+/** Suffix to y label values, none if unset. */
+@property (nonatomic) NSString *yLabelSuffix;
+
+@property (nonatomic) CGFloat chartMarginLeft;
+@property (nonatomic) CGFloat chartMarginRight;
+@property (nonatomic) CGFloat chartMarginTop;
+@property (nonatomic) CGFloat chartMarginBottom;
+
+/** Controls whether labels should be displayed. */
+@property (nonatomic) BOOL showLabel;
+
+/** Controls whether the chart border line should be displayed. */
+@property (nonatomic) BOOL showChartBorder;
+
+@property (nonatomic) UIColor *chartBorderColor;
+
+/** Controls whether the chart Horizontal separator should be displayed. */
+@property (nonatomic, assign) BOOL showLevelLine;
+
+/** Chart bottom border, co-linear with the x-axis. */
+@property (nonatomic) CAShapeLayer * chartBottomLine;
+
+/** Chart bottom border, level separator-linear with the x-axis. */
+@property (nonatomic) CAShapeLayer * chartLevelLine;
+
+/** Chart left border, co-linear with the y-axis. */
+@property (nonatomic) CAShapeLayer * chartLeftLine;
+
+/** Corner radius for all bars in the chart. */
+@property (nonatomic) CGFloat barRadius;
+
+/** Width of all bars in the chart. */
+@property (nonatomic) CGFloat barWidth;
+
+@property (nonatomic) CGFloat labelMarginTop;
+
+/** Background color of all bars in the chart. */
+@property (nonatomic) UIColor * barBackgroundColor;
+
+/** Text color for all bars in the chart. */
+@property (nonatomic) UIColor * labelTextColor;
+
+/** Font for all bars in the chart. */
+@property (nonatomic) UIFont * labelFont;
+
+/** How many labels on the x-axis to skip in between displaying labels. */
+@property (nonatomic) NSInteger xLabelSkip;
+
+/** How many labels on the y-axis to skip in between displaying labels. */
+@property (nonatomic) NSInteger yLabelSum;
+
+/** The maximum for the range of values to display on the y-axis. */
+@property (nonatomic) CGFloat yMaxValue;
+
+/** The minimum for the range of values to display on the y-axis. */
+@property (nonatomic) CGFloat yMinValue;
+
+/** Controls whether each bar should have a gradient fill. */
+@property (nonatomic) UIColor *barColorGradientStart;
+
+/** Controls whether text for x-axis be straight or rotate 45 degree. */
+@property (nonatomic) BOOL rotateForXAxisText;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+/**whether show gradient bar*/
+@property (nonatomic, assign) BOOL isGradientShow;
+
+/** whether show numbers*/
+@property (nonatomic, assign) BOOL isShowNumbers;
+
+@end
diff --git a/PNChartdemo/PNChart/PNBarChart.m b/PNChartdemo/PNChart/PNBarChart.m
new file mode 100755
index 0000000..50e035c
--- /dev/null
+++ b/PNChartdemo/PNChart/PNBarChart.m
@@ -0,0 +1,459 @@
+//
+//  PNBarChart.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNBarChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+
+@interface PNBarChart () {
+    NSMutableArray *_xChartLabels;
+    NSMutableArray *_yChartLabels;
+}
+
+- (UIColor *)barColorAtIndex:(NSUInteger)index;
+
+@end
+
+@implementation PNBarChart
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    [super setupDefaultValues];
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds   = YES;
+    _showLabel           = YES;
+    _barBackgroundColor  = PNLightGrey;
+    _labelTextColor      = [UIColor grayColor];
+    _labelFont           = [UIFont systemFontOfSize:11.0f];
+    _xChartLabels        = [NSMutableArray array];
+    _yChartLabels        = [NSMutableArray array];
+    _bars                = [NSMutableArray array];
+    _xLabelSkip          = 1;
+    _yLabelSum           = 4;
+    _labelMarginTop      = 2;
+    _chartMarginLeft     = 25.0;
+    _chartMarginRight    = 25.0;
+    _chartMarginTop      = 25.0;
+    _chartMarginBottom   = 25.0;
+    _barRadius           = 2.0;
+    _showChartBorder     = NO;
+    _chartBorderColor    = PNLightGrey;
+    _showLevelLine       = NO;
+    _yChartLabelWidth    = 18;
+    _rotateForXAxisText  = false;
+    _isGradientShow      = YES;
+    _isShowNumbers       = YES;
+    _yLabelPrefix        = @"";
+    _yLabelSuffix        = @"";
+	_yLabelFormatter = ^(CGFloat yValue){
+		return [NSString stringWithFormat:@"%1.f",yValue];
+	};
+}
+
+- (void)setYValues:(NSArray *)yValues
+{
+    _yValues = yValues;
+  //make the _yLabelSum value dependant of the distinct values of yValues to avoid duplicates on yAxis
+
+  if (_showLabel) {
+    [self __addYCoordinateLabelsValues];
+  } else {
+    [self processYMaxValue];
+  }
+}
+
+- (void)processYMaxValue {
+    NSArray *yAxisValues = _yLabels ? _yLabels : _yValues;
+    _yLabelSum = _yLabels ? _yLabels.count - 1 :_yLabelSum;
+    if (_yMaxValue) {
+        _yValueMax = _yMaxValue;
+    } else {
+        [self getYValueMax:yAxisValues];
+    }
+
+    if (_yLabelSum==4) {
+        _yLabelSum = yAxisValues.count;
+        (_yLabelSum % 2 == 0) ? _yLabelSum : _yLabelSum++;
+    }
+}
+
+#pragma mark - Private Method
+#pragma mark - Add Y Label
+- (void)__addYCoordinateLabelsValues{
+
+  [self viewCleanupForCollection:_yChartLabels];
+
+  [self processYMaxValue];
+
+  float sectionHeight = (self.frame.size.height - _chartMarginTop - _chartMarginBottom - kXLabelHeight) / _yLabelSum;
+    
+  for (int i = 0; i <= _yLabelSum; i++) {
+    NSString *labelText;
+    if (_yLabels) {
+      float yAsixValue = [_yLabels[_yLabels.count - i - 1] floatValue];
+      labelText= _yLabelFormatter(yAsixValue);
+    } else {
+      labelText = _yLabelFormatter((float)_yValueMax * ( (_yLabelSum - i) / (float)_yLabelSum ));
+    }
+
+    PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectZero];
+    label.font = _labelFont;
+    label.textColor = _labelTextColor;
+    [label setTextAlignment:NSTextAlignmentRight];
+    label.text = [NSString stringWithFormat:@"%@%@%@", _yLabelPrefix, labelText, _yLabelSuffix];
+    
+    [self addSubview:label];
+      
+    label.frame = (CGRect){0, sectionHeight * i + _chartMarginTop - kYLabelHeight/2.0 + kXLabelHeight + _labelMarginTop, _yChartLabelWidth, kYLabelHeight};
+
+    [_yChartLabels addObject:label];
+  }
+}
+
+-(void)updateChartData:(NSArray *)data{
+    self.yValues = data;
+    [self updateBar];
+}
+
+- (void)getYValueMax:(NSArray *)yLabels
+{
+    CGFloat max = [[yLabels valueForKeyPath:@"@max.floatValue"] floatValue];
+
+    //ensure max is even
+   _yValueMax = max ;
+
+    if (_yValueMax == 0) {
+        _yValueMax = _yMinValue;
+    }
+}
+
+- (void)setXLabels:(NSArray *)xLabels
+{
+    _xLabels = xLabels;
+
+    if (_xChartLabels) {
+        [self viewCleanupForCollection:_xChartLabels];
+    }else{
+        _xChartLabels = [NSMutableArray new];
+    }
+
+	_xLabelWidth = (self.frame.size.width - _chartMarginLeft - _chartMarginRight) / [xLabels count];
+
+    if (_showLabel) {
+        int labelAddCount = 0;
+        for (int index = 0; index < _xLabels.count; index++) {
+            labelAddCount += 1;
+
+            if (labelAddCount == _xLabelSkip) {
+                NSString *labelText = [_xLabels[index] description];
+                PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0, 0, _xLabelWidth, kXLabelHeight)];
+                label.font = _labelFont;
+                label.textColor = _labelTextColor;
+                [label setTextAlignment:NSTextAlignmentCenter];
+                label.text = labelText;
+                //[label sizeToFit];
+                CGFloat labelXPosition;
+                if (_rotateForXAxisText){
+                    label.transform = CGAffineTransformMakeRotation(M_PI / 4);
+                    labelXPosition = (index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /1.5);
+                }
+                else{
+                    labelXPosition = (index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0 );
+                }
+                label.center = CGPointMake(labelXPosition,
+                                           self.frame.size.height - _chartMarginTop + label.frame.size.height /2.0 + _labelMarginTop);
+                labelAddCount = 0;
+
+                [_xChartLabels addObject:label];
+                [self addSubview:label];
+            }
+        }
+    }
+}
+
+
+- (void)setStrokeColor:(UIColor *)strokeColor
+{
+    _strokeColor = strokeColor;
+}
+
+- (void)updateBar
+{
+
+    //Add bars
+    CGFloat chartCavanHeight = self.frame.size.height - _chartMarginTop - _chartMarginBottom - kXLabelHeight;
+    NSInteger index = 0;
+
+    for (NSNumber *valueString in _yValues) {
+
+        PNBar *bar;
+
+        if (_bars.count == _yValues.count) {
+            bar = [_bars objectAtIndex:index];
+        }else{
+            CGFloat barWidth;
+            CGFloat barXPosition;
+
+            if (_barWidth) {
+                barWidth = _barWidth;
+                barXPosition = index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0 - _barWidth /2.0;
+            }else{
+                barXPosition = index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth * 0.25;
+                if (_showLabel) {
+                    barWidth = _xLabelWidth * 0.5;
+
+                }
+                else {
+                    barWidth = _xLabelWidth * 0.6;
+
+                }
+            }
+
+            bar = [[PNBar alloc] initWithFrame:CGRectMake(barXPosition, //Bar X position
+                                                          self.frame.size.height - chartCavanHeight - kXLabelHeight - _chartMarginBottom + _chartMarginTop , //Bar Y position
+                                                          barWidth, // Bar witdh
+                                                          self.showLevelLine ? chartCavanHeight/2.0:chartCavanHeight)]; //Bar height
+
+            //Change Bar Radius
+            bar.barRadius = _barRadius;
+            
+            //Set Bar Animation
+            bar.displayAnimated = self.displayAnimated;
+
+            //Change Bar Background color
+            bar.backgroundColor = _barBackgroundColor;
+            //Bar StrokColor First
+            if (self.strokeColor) {
+                bar.barColor = self.strokeColor;
+            }else{
+                bar.barColor = [self barColorAtIndex:index];
+            }
+            
+            if (self.labelTextColor) {
+                bar.labelTextColor = self.labelTextColor;
+            }
+
+            // Add gradient
+            if (self.isGradientShow) {
+             bar.barColorGradientStart = bar.barColor;
+            }
+
+            //For Click Index
+            bar.tag = index;
+
+            [_bars addObject:bar];
+            [self addSubview:bar];
+        }
+
+        //Height Of Bar
+        float value = [valueString floatValue];
+        float grade =fabsf((float)value / (float)_yValueMax);
+
+        if (isnan(grade)) {
+            grade = 0;
+        }
+        bar.maxDivisor = (float)_yValueMax;
+        bar.grade = grade;
+        bar.isShowNumber = self.isShowNumbers;
+        CGRect originalFrame = bar.frame;
+        NSString *currentNumber =  [NSString stringWithFormat:@"%f",value];
+
+        if ([[currentNumber substringToIndex:1] isEqualToString:@"-"] && self.showLevelLine) {
+        CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);
+        [bar setTransform:transform];
+        originalFrame.origin.y = bar.frame.origin.y + bar.frame.size.height;
+        bar.frame = originalFrame;
+        bar.isNegative = YES;
+
+      }
+      index += 1;
+    }
+}
+
+- (void)strokeChart
+{
+    //Add Labels
+
+    [self viewCleanupForCollection:_bars];
+
+
+    //Update Bar
+
+    [self updateBar];
+
+    //Add chart border lines
+
+    if (_showChartBorder) {
+        _chartBottomLine = [CAShapeLayer layer];
+        _chartBottomLine.lineCap      = kCALineCapButt;
+        _chartBottomLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartBottomLine.lineWidth    = 1.0;
+        _chartBottomLine.strokeEnd    = 0.0;
+
+        UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+        [progressline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+        [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginRight,  self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+
+        [progressline setLineWidth:1.0];
+        [progressline setLineCapStyle:kCGLineCapSquare];
+        _chartBottomLine.path = progressline.CGPath;
+        _chartBottomLine.strokeColor = [_chartBorderColor CGColor];;
+        _chartBottomLine.strokeEnd = 1.0;
+
+        [self.layer addSublayer:_chartBottomLine];
+
+        //Add left Chart Line
+
+        _chartLeftLine = [CAShapeLayer layer];
+        _chartLeftLine.lineCap      = kCALineCapButt;
+        _chartLeftLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartLeftLine.lineWidth    = 1.0;
+        _chartLeftLine.strokeEnd    = 0.0;
+
+        UIBezierPath *progressLeftline = [UIBezierPath bezierPath];
+
+        [progressLeftline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+        [progressLeftline addLineToPoint:CGPointMake(_chartMarginLeft,  _chartMarginTop)];
+
+        [progressLeftline setLineWidth:1.0];
+        [progressLeftline setLineCapStyle:kCGLineCapSquare];
+        _chartLeftLine.path = progressLeftline.CGPath;
+        _chartLeftLine.strokeColor = [_chartBorderColor CGColor];
+        _chartLeftLine.strokeEnd = 1.0;
+
+        [self addBorderAnimationIfNeeded];
+        [self.layer addSublayer:_chartLeftLine];
+    }
+
+  // Add Level Separator Line
+  if (_showLevelLine) {
+    _chartLevelLine = [CAShapeLayer layer];
+    _chartLevelLine.lineCap      = kCALineCapButt;
+    _chartLevelLine.fillColor    = [[UIColor whiteColor] CGColor];
+    _chartLevelLine.lineWidth    = 1.0;
+    _chartLevelLine.strokeEnd    = 0.0;
+
+    UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+    [progressline moveToPoint:CGPointMake(_chartMarginLeft, (self.frame.size.height - kXLabelHeight )/2.0)];
+    [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginLeft - _chartMarginRight,  (self.frame.size.height - kXLabelHeight )/2.0)];
+
+    [progressline setLineWidth:1.0];
+    [progressline setLineCapStyle:kCGLineCapSquare];
+    _chartLevelLine.path = progressline.CGPath;
+
+    _chartLevelLine.strokeColor = PNLightGrey.CGColor;
+      
+    [self addSeparatorAnimationIfNeeded];
+    _chartLevelLine.strokeEnd = 1.0;
+
+    [self.layer addSublayer:_chartLevelLine];
+  } else {
+    if (_chartLevelLine) {
+      [_chartLevelLine removeFromSuperlayer];
+      _chartLevelLine = nil;
+    }
+  }
+}
+
+- (void)addBorderAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = 0.5;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @0.0f;
+        pathAnimation.toValue = @1.0f;
+        [_chartBottomLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        
+        CABasicAnimation *pathLeftAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathLeftAnimation.duration = 0.5;
+        pathLeftAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathLeftAnimation.fromValue = @0.0f;
+        pathLeftAnimation.toValue = @1.0f;
+        [_chartLeftLine addAnimation:pathLeftAnimation forKey:@"strokeEndAnimation"];
+    }
+}
+
+- (void)addSeparatorAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = 0.5;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @0.0f;
+        pathAnimation.toValue = @1.0f;
+        [_chartLevelLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+    }
+}
+
+- (void)viewCleanupForCollection:(NSMutableArray *)array
+{
+    if (array.count) {
+        [array makeObjectsPerformSelector:@selector(removeFromSuperview)];
+        [array removeAllObjects];
+    }
+}
+
+
+#pragma mark - Class extension methods
+
+- (UIColor *)barColorAtIndex:(NSUInteger)index
+{
+    if ([self.strokeColors count] == [self.yValues count]) {
+        return self.strokeColors[index];
+    }
+    else {
+        return self.strokeColor;
+    }
+}
+
+#pragma mark - Touch detection
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    [self touchPoint:touches withEvent:event];
+    [super touchesBegan:touches withEvent:event];
+}
+
+- (void)touchPoint:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    //Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+    UIView *subview = [self hitTest:touchPoint withEvent:nil];
+
+    if ([subview isKindOfClass:[PNBar class]] && [self.delegate respondsToSelector:@selector(userClickedOnBarAtIndex:)]) {
+        [self.delegate userClickedOnBarAtIndex:subview.tag];
+    }
+}
+
+
+@end
diff --git a/PNChartdemo/PNChart/PNChart.h b/PNChartdemo/PNChart/PNChart.h
new file mode 100755
index 0000000..0835d39
--- /dev/null
+++ b/PNChartdemo/PNChart/PNChart.h
@@ -0,0 +1,22 @@
+//
+//  PNChart.h
+//	Version 0.1
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNChart.h"
+#import "PNColor.h"
+#import "PNLineChart.h"
+#import "PNLineChartData.h"
+#import "PNLineChartDataItem.h"
+#import "PNBarChart.h"
+#import "PNCircleChart.h"
+#import "PNChartDelegate.h"
+#import "PNPieChart.h"
+#import "PNScatterChart.h"
+#import "PNRadarChart.h"
+#import "PNRadarChartDataItem.h"
diff --git a/PNChartdemo/PNChart/PNChartDelegate.h b/PNChartdemo/PNChart/PNChartDelegate.h
new file mode 100755
index 0000000..6d49f7c
--- /dev/null
+++ b/PNChartdemo/PNChart/PNChartDelegate.h
@@ -0,0 +1,33 @@
+//
+//  PNChartDelegate.h
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-12-11.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol PNChartDelegate <NSObject>
+@optional
+/**
+ * Callback method that gets invoked when the user taps on the chart line.
+ */
+- (void)userClickedOnLinePoint:(CGPoint)point lineIndex:(NSInteger)lineIndex;
+
+/**
+ * Callback method that gets invoked when the user taps on a chart line key point.
+ */
+- (void)userClickedOnLineKeyPoint:(CGPoint)point
+                        lineIndex:(NSInteger)lineIndex
+                       pointIndex:(NSInteger)pointIndex;
+
+/**
+ * Callback method that gets invoked when the user taps on a chart bar.
+ */
+- (void)userClickedOnBarAtIndex:(NSInteger)barIndex;
+
+
+- (void)userClickedOnPieIndexItem:(NSInteger)pieIndex;
+- (void)didUnselectPieItem;
+@end
diff --git a/PNChartdemo/PNChart/PNChartLabel.h b/PNChartdemo/PNChart/PNChartLabel.h
new file mode 100755
index 0000000..9ba6afa
--- /dev/null
+++ b/PNChartdemo/PNChart/PNChartLabel.h
@@ -0,0 +1,13 @@
+//
+//  PNChartLabel.h
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface PNChartLabel : UILabel
+
+@end
diff --git a/PNChartdemo/PNChart/PNChartLabel.m b/PNChartdemo/PNChart/PNChartLabel.m
new file mode 100755
index 0000000..b0980d1
--- /dev/null
+++ b/PNChartdemo/PNChart/PNChartLabel.m
@@ -0,0 +1,32 @@
+//
+//  PNChartLabel.m
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNChartLabel.h"
+
+@implementation PNChartLabel
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        self.font                      = [UIFont boldSystemFontOfSize:11.0f];
+        self.backgroundColor           = [UIColor clearColor];
+        self.textAlignment             = NSTextAlignmentCenter;
+        self.userInteractionEnabled    = YES;
+        self.adjustsFontSizeToFitWidth = YES;
+        self.numberOfLines             = 0;
+        /* if you want to see ... in large labels un-comment this line
+        self.minimumScaleFactor        = 0.8;
+        */
+    }
+
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNCircleChart.h b/PNChartdemo/PNChart/PNCircleChart.h
new file mode 100755
index 0000000..f9fc06d
--- /dev/null
+++ b/PNChartdemo/PNChart/PNCircleChart.h
@@ -0,0 +1,74 @@
+//
+//  PNCircleChart.h
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-11-30.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNColor.h"
+#import "UICountingLabel.h"
+
+typedef NS_ENUM (NSUInteger, PNChartFormatType) {
+    PNChartFormatTypePercent,
+    PNChartFormatTypeDollar,
+    PNChartFormatTypeNone,
+    PNChartFormatTypeDecimal,
+    PNChartFormatTypeDecimalTwoPlaces,
+};
+
+#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
+
+@interface PNCircleChart : UIView
+
+- (void)strokeChart;
+- (void)growChartByAmount:(NSNumber *)growAmount;
+- (void)updateChartByCurrent:(NSNumber *)current;
+- (void)updateChartByCurrent:(NSNumber *)current byTotal:(NSNumber *)total;
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel
+  overrideLineWidth:(NSNumber *)overrideLineWidth;
+
+@property (strong, nonatomic) UICountingLabel *countingLabel;
+@property (nonatomic) UIColor *strokeColor;
+@property (nonatomic) UIColor *strokeColorGradientStart;
+@property (nonatomic) NSNumber *total;
+@property (nonatomic) NSNumber *current;
+@property (nonatomic) NSNumber *lineWidth;
+@property (nonatomic) NSTimeInterval duration;
+@property (nonatomic) PNChartFormatType chartType;
+
+@property (nonatomic) CAShapeLayer *circle;
+@property (nonatomic) CAShapeLayer *gradientMask;
+@property (nonatomic) CAShapeLayer *circleBackground;
+
+@property (nonatomic) BOOL displayCountingLabel;
+@property (nonatomic) BOOL displayAnimated;
+
+@end
diff --git a/PNChartdemo/PNChart/PNCircleChart.m b/PNChartdemo/PNChart/PNCircleChart.m
new file mode 100755
index 0000000..19f70e5
--- /dev/null
+++ b/PNChartdemo/PNChart/PNCircleChart.m
@@ -0,0 +1,267 @@
+//
+//  PNCircleChart.m
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-11-30.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNCircleChart.h"
+
+@interface PNCircleChart ()
+@end
+
+@implementation PNCircleChart
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:NO
+                   shadowColor:[UIColor clearColor]
+          displayCountingLabel:YES
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:shadow
+                   shadowColor:backgroundShadowColor
+          displayCountingLabel:YES
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor displayCountingLabel:(BOOL)displayCountingLabel {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:shadow
+                   shadowColor:backgroundShadowColor
+          displayCountingLabel:displayCountingLabel
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel
+  overrideLineWidth:(NSNumber *)overrideLineWidth
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        _total = total;
+        _current = current;
+        _strokeColor = PNFreshGreen;
+        _duration = 1.0;
+        _chartType = PNChartFormatTypePercent;
+        _displayAnimated = YES;
+        
+        _displayCountingLabel = displayCountingLabel;
+
+        CGFloat startAngle = clockwise ? -90.0f : 270.0f;
+        CGFloat endAngle = clockwise ? -90.01f : 270.01f;
+
+        _lineWidth = overrideLineWidth;
+        
+        UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)
+                                                                  radius:(self.frame.size.height * 0.5) - ([_lineWidth floatValue]/2.0f)
+                                                              startAngle:DEGREES_TO_RADIANS(startAngle)
+                                                                endAngle:DEGREES_TO_RADIANS(endAngle)
+                                                               clockwise:clockwise];
+
+        _circle               = [CAShapeLayer layer];
+        _circle.path          = circlePath.CGPath;
+        _circle.lineCap       = kCALineCapRound;
+        _circle.fillColor     = [UIColor clearColor].CGColor;
+        _circle.lineWidth     = [_lineWidth floatValue];
+        _circle.zPosition     = 1;
+
+        _circleBackground             = [CAShapeLayer layer];
+        _circleBackground.path        = circlePath.CGPath;
+        _circleBackground.lineCap     = kCALineCapRound;
+        _circleBackground.fillColor   = [UIColor clearColor].CGColor;
+        _circleBackground.lineWidth   = [_lineWidth floatValue];
+        _circleBackground.strokeColor = (hasBackgroundShadow ? backgroundShadowColor.CGColor : [UIColor clearColor].CGColor);
+        _circleBackground.strokeEnd   = 1.0;
+        _circleBackground.zPosition   = -1;
+
+        [self.layer addSublayer:_circle];
+        [self.layer addSublayer:_circleBackground];
+
+        _countingLabel = [[UICountingLabel alloc] initWithFrame:CGRectMake(0, 0, 100.0, 50.0)];
+        [_countingLabel setTextAlignment:NSTextAlignmentCenter];
+        [_countingLabel setFont:[UIFont boldSystemFontOfSize:16.0f]];
+        [_countingLabel setTextColor:[UIColor grayColor]];
+        [_countingLabel setBackgroundColor:[UIColor clearColor]];
+        [_countingLabel setCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)];
+        _countingLabel.method = UILabelCountingMethodEaseInOut;
+        if (_displayCountingLabel) {
+            [self addSubview:_countingLabel];
+        }
+    }
+
+    return self;
+}
+
+
+- (void)strokeChart
+{
+    // Add counting label
+
+    if (_displayCountingLabel) {
+        NSString *format;
+        switch (self.chartType) {
+            case PNChartFormatTypePercent:
+                format = @"%d%%";
+                break;
+            case PNChartFormatTypeDollar:
+                format = @"$%d";
+                break;
+            case PNChartFormatTypeDecimal:
+                format = @"%.1f";
+                break;
+            case PNChartFormatTypeDecimalTwoPlaces:
+                format = @"%.2f";
+                break;
+            case PNChartFormatTypeNone:
+            default:
+                format = @"%d";
+                break;
+        }
+        self.countingLabel.format = format;
+        [self addSubview:self.countingLabel];
+    }
+
+
+    // Add circle params
+
+    _circle.lineWidth   = [_lineWidth floatValue];
+    _circleBackground.lineWidth = [_lineWidth floatValue];
+    _circleBackground.strokeEnd = 1.0;
+    _circle.strokeColor = _strokeColor.CGColor;
+    _circle.strokeEnd   = [_current floatValue] / [_total floatValue];
+
+    // Check if user wants to add a gradient from the start color to the bar color
+    if (_strokeColorGradientStart) {
+
+        // Add gradient
+        self.gradientMask = [CAShapeLayer layer];
+        self.gradientMask.fillColor = [[UIColor clearColor] CGColor];
+        self.gradientMask.strokeColor = [[UIColor blackColor] CGColor];
+        self.gradientMask.lineWidth = _circle.lineWidth;
+        self.gradientMask.lineCap = kCALineCapRound;
+        CGRect gradientFrame = CGRectMake(0, 0, 2*self.bounds.size.width, 2*self.bounds.size.height);
+        self.gradientMask.frame = gradientFrame;
+        self.gradientMask.path = _circle.path;
+
+        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
+        gradientLayer.startPoint = CGPointMake(0.5,1.0);
+        gradientLayer.endPoint = CGPointMake(0.5,0.0);
+        gradientLayer.frame = gradientFrame;
+        UIColor *endColor = (_strokeColor ? _strokeColor : [UIColor greenColor]);
+        NSArray *colors = @[
+                            (id)endColor.CGColor,
+                            (id)_strokeColorGradientStart.CGColor
+                            ];
+        gradientLayer.colors = colors;
+
+        [gradientLayer setMask:self.gradientMask];
+
+        [_circle addSublayer:gradientLayer];
+
+        self.gradientMask.strokeEnd = [_current floatValue] / [_total floatValue];
+    }
+    
+    [self addAnimationIfNeeded];
+}
+
+
+
+- (void)growChartByAmount:(NSNumber *)growAmount
+{
+    NSNumber *updatedValue = [NSNumber numberWithFloat:[_current floatValue] + [growAmount floatValue]];
+
+    // Add animation
+    [self updateChartByCurrent:updatedValue];
+}
+
+
+-(void)updateChartByCurrent:(NSNumber *)current{
+    
+    [self updateChartByCurrent:current
+                       byTotal:_total];
+    
+}
+
+-(void)updateChartByCurrent:(NSNumber *)current byTotal:(NSNumber *)total {
+    double totalPercentageValue = [current floatValue]/([total floatValue]/100.0);
+    
+    if (_strokeColorGradientStart) {
+        self.gradientMask.strokeEnd = _circle.strokeEnd;
+    }
+    
+    // Add animation
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = self.duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @([_current floatValue] / [_total floatValue]);
+        pathAnimation.toValue = @([current floatValue] / [total floatValue]);
+        
+        if (_strokeColorGradientStart) {
+            [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+        [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        
+        if (_displayCountingLabel) {
+            [self.countingLabel countFrom:fmin([_current floatValue], [_total floatValue]) to:totalPercentageValue withDuration:self.duration];
+        }
+        
+    }
+    else if (_displayCountingLabel) {
+        [self.countingLabel countFrom:totalPercentageValue to:totalPercentageValue withDuration:self.duration];
+    }
+    
+    _circle.strokeEnd   = [current floatValue] / [total floatValue];
+    _current = current;
+    _total = total;
+}
+
+- (void)addAnimationIfNeeded
+{
+    double percentageValue = [_current floatValue]/([_total floatValue]/100.0);
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = self.duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @(0.0f);
+        pathAnimation.toValue = @([_current floatValue] / [_total floatValue]);
+        [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        [_countingLabel countFrom:0 to:percentageValue withDuration:self.duration];
+        
+        if (self.gradientMask && _strokeColorGradientStart) {
+            [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+    }
+    else {
+        [_countingLabel countFrom:percentageValue to:percentageValue withDuration:self.duration];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNColor.h b/PNChartdemo/PNChart/PNColor.h
new file mode 100755
index 0000000..cfd3ff8
--- /dev/null
+++ b/PNChartdemo/PNChart/PNColor.h
@@ -0,0 +1,53 @@
+//
+//  PNColor.h
+//  PNChart
+//
+//  Created by kevin on 13-6-8.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+/*
+ *  System Versioning Preprocessor Macros
+ */
+
+#define SCREEN_WIDTH    ([UIScreen mainScreen].bounds.size.width)
+
+#define PNGrey          [UIColor colorWithRed:246.0 / 255.0 green:246.0 / 255.0 blue:246.0 / 255.0 alpha:1.0f]
+#define PNLightBlue     [UIColor colorWithRed:94.0 / 255.0 green:147.0 / 255.0 blue:196.0 / 255.0 alpha:1.0f]
+#define PNGreen         [UIColor colorWithRed:77.0 / 255.0 green:186.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNTitleColor    [UIColor colorWithRed:0.0 / 255.0 green:189.0 / 255.0 blue:113.0 / 255.0 alpha:1.0f]
+#define PNButtonGrey    [UIColor colorWithRed:141.0 / 255.0 green:141.0 / 255.0 blue:141.0 / 255.0 alpha:1.0f]
+#define PNLightGreen    [UIColor colorWithRed:77.0 / 255.0 green:216.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNFreshGreen    [UIColor colorWithRed:77.0 / 255.0 green:196.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNDeepGreen     [UIColor colorWithRed:77.0 / 255.0 green:176.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNRed           [UIColor colorWithRed:245.0 / 255.0 green:94.0 / 255.0 blue:78.0 / 255.0 alpha:1.0f]
+#define PNMauve         [UIColor colorWithRed:88.0 / 255.0 green:75.0 / 255.0 blue:103.0 / 255.0 alpha:1.0f]
+#define PNBrown         [UIColor colorWithRed:119.0 / 255.0 green:107.0 / 255.0 blue:95.0 / 255.0 alpha:1.0f]
+#define PNBlue          [UIColor colorWithRed:82.0 / 255.0 green:116.0 / 255.0 blue:188.0 / 255.0 alpha:1.0f]
+#define PNDarkBlue      [UIColor colorWithRed:121.0 / 255.0 green:134.0 / 255.0 blue:142.0 / 255.0 alpha:1.0f]
+#define PNYellow        [UIColor colorWithRed:242.0 / 255.0 green:197.0 / 255.0 blue:117.0 / 255.0 alpha:1.0f]
+#define PNWhite         [UIColor colorWithRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:1.0f]
+#define PNDeepGrey      [UIColor colorWithRed:99.0 / 255.0 green:99.0 / 255.0 blue:99.0 / 255.0 alpha:1.0f]
+#define PNPinkGrey      [UIColor colorWithRed:200.0 / 255.0 green:193.0 / 255.0 blue:193.0 / 255.0 alpha:1.0f]
+#define PNHealYellow    [UIColor colorWithRed:245.0 / 255.0 green:242.0 / 255.0 blue:238.0 / 255.0 alpha:1.0f]
+#define PNLightGrey     [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:225.0 / 255.0 alpha:1.0f]
+#define PNCleanGrey     [UIColor colorWithRed:251.0 / 255.0 green:251.0 / 255.0 blue:251.0 / 255.0 alpha:1.0f]
+#define PNLightYellow   [UIColor colorWithRed:241.0 / 255.0 green:240.0 / 255.0 blue:240.0 / 255.0 alpha:1.0f]
+#define PNDarkYellow    [UIColor colorWithRed:152.0 / 255.0 green:150.0 / 255.0 blue:159.0 / 255.0 alpha:1.0f]
+#define PNPinkDark      [UIColor colorWithRed:170.0 / 255.0 green:165.0 / 255.0 blue:165.0 / 255.0 alpha:1.0f]
+#define PNCloudWhite    [UIColor colorWithRed:244.0 / 255.0 green:244.0 / 255.0 blue:244.0 / 255.0 alpha:1.0f]
+#define PNBlack         [UIColor colorWithRed:45.0 / 255.0 green:45.0 / 255.0 blue:45.0 / 255.0 alpha:1.0f]
+#define PNStarYellow    [UIColor colorWithRed:252.0 / 255.0 green:223.0 / 255.0 blue:101.0 / 255.0 alpha:1.0f]
+#define PNTwitterColor  [UIColor colorWithRed:0.0 / 255.0 green:171.0 / 255.0 blue:243.0 / 255.0 alpha:1.0]
+#define PNWeiboColor    [UIColor colorWithRed:250.0 / 255.0 green:0.0 / 255.0 blue:33.0 / 255.0 alpha:1.0]
+#define PNiOSGreenColor [UIColor colorWithRed:98.0 / 255.0 green:247.0 / 255.0 blue:77.0 / 255.0 alpha:1.0]
+
+
+@interface PNColor : NSObject
+
+- (UIImage *)imageFromColor:(UIColor *)color;
+
+@end
diff --git a/PNChartdemo/PNChart/PNColor.m b/PNChartdemo/PNChart/PNColor.m
new file mode 100755
index 0000000..2ebc8c0
--- /dev/null
+++ b/PNChartdemo/PNChart/PNColor.m
@@ -0,0 +1,29 @@
+//
+//  PNColor.m
+//  PNChart
+//
+//  Created by kevin on 13-6-8.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNColor.h"
+#import <UIKit/UIKit.h>
+
+@implementation PNColor
+
+- (UIImage *)imageFromColor:(UIColor *)color
+{
+    CGRect rect = CGRectMake(0, 0, 1, 1);
+
+    UIGraphicsBeginImageContext(rect.size);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextSetFillColorWithColor(context, [color CGColor]);
+    CGContextFillRect(context, rect);
+    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+
+    return img;
+}
+
+
+@end
diff --git a/PNChartdemo/PNChart/PNGenericChart.h b/PNChartdemo/PNChart/PNGenericChart.h
new file mode 100755
index 0000000..829d84a
--- /dev/null
+++ b/PNChartdemo/PNChart/PNGenericChart.h
@@ -0,0 +1,48 @@
+//
+//  PNGenericChart.h
+//  PNChartDemo
+//
+//  Created by Andi Palo on 26/02/15.
+//  Copyright (c) 2015 kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNLegendPosition) {
+    PNLegendPositionTop = 0,
+    PNLegendPositionBottom = 1,
+    PNLegendPositionLeft = 2,
+    PNLegendPositionRight = 3
+};
+
+typedef NS_ENUM(NSUInteger, PNLegendItemStyle) {
+    PNLegendItemStyleStacked = 0,
+    PNLegendItemStyleSerial = 1
+};
+
+@interface PNGenericChart : UIView
+
+@property (assign, nonatomic) BOOL hasLegend;
+@property (assign, nonatomic) PNLegendPosition legendPosition;
+@property (assign, nonatomic) PNLegendItemStyle legendStyle;
+
+@property (assign, nonatomic) UIFont *legendFont;
+@property (assign, nonatomic) UIColor *legendFontColor;
+@property (assign, nonatomic) NSUInteger labelRowsInSerialMode;
+
+/** Display the chart with or without animation. Default is YES. **/
+@property (nonatomic) BOOL displayAnimated;
+
+/**
+ *  returns the Legend View, or nil if no chart data is present.
+ *  The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect)
+ *
+ *  @param mWidth Maximum width of legend. Height will depend on this and font size
+ *
+ *  @return UIView of Legend
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth;
+
+
+- (void) setupDefaultValues;
+@end
diff --git a/PNChartdemo/PNChart/PNGenericChart.m b/PNChartdemo/PNChart/PNGenericChart.m
new file mode 100755
index 0000000..c54ac37
--- /dev/null
+++ b/PNChartdemo/PNChart/PNGenericChart.m
@@ -0,0 +1,54 @@
+//
+//  PNGenericChart.m
+//  PNChartDemo
+//
+//  Created by Andi Palo on 26/02/15.
+//  Copyright (c) 2015 kevinzhow. All rights reserved.
+//
+
+#import "PNGenericChart.h"
+
+@interface PNGenericChart ()
+
+
+
+@end
+
+@implementation PNGenericChart
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+- (void) setupDefaultValues{
+    self.hasLegend = YES;
+    self.legendPosition = PNLegendPositionBottom;
+    self.legendStyle = PNLegendItemStyleStacked;
+    self.labelRowsInSerialMode = 1;
+    self.displayAnimated = YES;
+}
+
+
+
+/**
+ *  to be implemented in subclass 
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{
+    [self doesNotRecognizeSelector:_cmd];
+    return nil;
+}
+
+- (void) setLabelRowsInSerialMode:(NSUInteger)num{
+    if (self.legendStyle == PNLegendItemStyleSerial) {
+        _labelRowsInSerialMode = num;
+    }else{
+        _labelRowsInSerialMode = 1;
+    }
+}
+
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChart.h b/PNChartdemo/PNChart/PNLineChart.h
new file mode 100755
index 0000000..b30878a
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChart.h
@@ -0,0 +1,110 @@
+//
+//  PNLineChart.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "PNChartDelegate.h"
+#import "PNGenericChart.h"
+
+@interface PNLineChart : PNGenericChart
+
+/**
+ * Draws the chart in an animated fashion.
+ */
+- (void)strokeChart;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+@property (nonatomic) NSArray *xLabels;
+@property (nonatomic) NSArray *yLabels;
+
+/**
+ * Array of `LineChartData` objects, one for each line.
+ */
+@property (nonatomic) NSArray *chartData;
+
+@property (nonatomic) NSMutableArray *pathPoints;
+@property (nonatomic) NSMutableArray *xChartLabels;
+@property (nonatomic) NSMutableArray *yChartLabels;
+
+@property (nonatomic) CGFloat xLabelWidth;
+@property (nonatomic) UIFont *xLabelFont;
+@property (nonatomic) UIColor *xLabelColor;
+@property (nonatomic) CGFloat yValueMax;
+@property (nonatomic) CGFloat yFixedValueMax;
+@property (nonatomic) CGFloat yFixedValueMin;
+@property (nonatomic) CGFloat yValueMin;
+@property (nonatomic) NSInteger yLabelNum;
+@property (nonatomic) CGFloat yLabelHeight;
+@property (nonatomic) UIFont *yLabelFont;
+@property (nonatomic) UIColor *yLabelColor;
+@property (nonatomic) CGFloat chartCavanHeight;
+@property (nonatomic) CGFloat chartCavanWidth;
+@property (nonatomic) BOOL showLabel;
+@property (nonatomic) BOOL showGenYLabels;
+@property (nonatomic) BOOL showYGridLines;
+@property (nonatomic) UIColor *yGridLinesColor;
+@property (nonatomic) BOOL thousandsSeparator;
+
+@property (nonatomic) CGFloat chartMarginLeft;
+@property (nonatomic) CGFloat chartMarginRight;
+@property (nonatomic) CGFloat chartMarginTop;
+@property (nonatomic) CGFloat chartMarginBottom;
+
+/**
+ * Controls whether to show the coordinate axis. Default is NO.
+ */
+@property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis;
+@property (nonatomic) UIColor *axisColor;
+@property (nonatomic) CGFloat axisWidth;
+
+@property (nonatomic, strong) NSString *xUnit;
+@property (nonatomic, strong) NSString *yUnit;
+
+/**
+ * String formatter for float values in y-axis labels. If not set, defaults to @"%1.f"
+ */
+@property (nonatomic, strong) NSString *yLabelFormat;
+
+/**
+ * Block formatter for custom string in y-axis labels. If not set, defaults to yLabelFormat
+ */
+@property (nonatomic, copy) NSString* (^yLabelBlockFormatter)(CGFloat);
+
+
+/**
+ * Controls whether to curve the line chart or not
+ */
+@property (nonatomic) BOOL showSmoothLines;
+
+- (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width;
+
+/**
+ * Update Chart Value
+ */
+
+- (void)updateChartData:(NSArray *)data;
+
+
+/**
+ *  returns the Legend View, or nil if no chart data is present. 
+ *  The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect)
+ *
+ *  @param mWidth Maximum width of legend. Height will depend on this and font size
+ *
+ *  @return UIView of Legend
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth;
+
+
++ (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font;
+
++ (CGPoint)midPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2;
++ (CGPoint)controlPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2;
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChart.m b/PNChartdemo/PNChart/PNLineChart.m
new file mode 100755
index 0000000..fda132d
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChart.m
@@ -0,0 +1,1285 @@
+//
+//  PNLineChart.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNLineChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+#import "PNLineChartData.h"
+#import "PNLineChartDataItem.h"
+
+@interface PNLineChart ()
+
+@property(nonatomic) NSMutableArray *chartLineArray;  // Array[CAShapeLayer]
+@property(nonatomic) NSMutableArray *chartPointArray; // Array[CAShapeLayer] save the point layer
+
+@property(nonatomic) NSMutableArray *chartPath;       // Array of line path, one for each line.
+@property(nonatomic) NSMutableArray *pointPath;       // Array of point path, one for each line
+@property(nonatomic) NSMutableArray *endPointsOfPath;      // Array of start and end points of each line path, one for each line
+
+@property(nonatomic) CABasicAnimation *pathAnimation; // will be set to nil if _displayAnimation is NO
+
+// display grade
+@property(nonatomic) NSMutableArray *gradeStringPaths;
+@property(nonatomic) NSMutableArray *progressLinePathsColors; //Array of colors when drawing each line.if chartData.rangeColors is set then different colors will be
+
+@end
+
+@implementation PNLineChart
+
+@synthesize pathAnimation = _pathAnimation;
+
+#pragma mark initialization
+
+- (id)initWithCoder:(NSCoder *)coder {
+    self = [super initWithCoder:coder];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+
+#pragma mark instance methods
+
+- (void)setYLabels {
+    CGFloat yStep = (_yValueMax - _yValueMin) / _yLabelNum;
+    CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+
+    if (_yChartLabels) {
+        for (PNChartLabel *label in _yChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _yChartLabels = [NSMutableArray new];
+    }
+
+    if (yStep == 0.0) {
+        PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger) _chartCavanHeight, (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        minLabel.text = [self formatYLabel:0.0];
+        [self setCustomStyleForYLabel:minLabel];
+        [self addSubview:minLabel];
+        [_yChartLabels addObject:minLabel];
+
+        PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger) (_chartCavanHeight / 2), (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        midLabel.text = [self formatYLabel:_yValueMax];
+        [self setCustomStyleForYLabel:midLabel];
+        [self addSubview:midLabel];
+        [_yChartLabels addObject:midLabel];
+
+        PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        maxLabel.text = [self formatYLabel:_yValueMax * 2];
+        [self setCustomStyleForYLabel:maxLabel];
+        [self addSubview:maxLabel];
+        [_yChartLabels addObject:maxLabel];
+
+    } else {
+        NSInteger index = 0;
+        NSInteger num = _yLabelNum + 1;
+
+        while (num > 0) {
+            CGRect labelFrame = CGRectMake(0.0,
+                    (NSInteger) (_chartCavanHeight + _chartMarginTop - index * yStepHeight),
+                    (CGFloat) ((NSInteger) _chartMarginLeft * 0.9),
+                    (NSInteger) _yLabelHeight);
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:labelFrame];
+            [label setTextAlignment:NSTextAlignmentRight];
+            label.text = [self formatYLabel:_yValueMin + (yStep * index)];
+            [self setCustomStyleForYLabel:label];
+            [self addSubview:label];
+            [_yChartLabels addObject:label];
+            index += 1;
+            num -= 1;
+        }
+    }
+}
+
+- (void)setYLabels:(NSArray *)yLabels {
+    _showGenYLabels = NO;
+    _yLabelNum = yLabels.count - 1;
+
+    CGFloat yLabelHeight;
+    if (_showLabel) {
+        yLabelHeight = _chartCavanHeight / [yLabels count];
+    } else {
+        yLabelHeight = (self.frame.size.height) / [yLabels count];
+    }
+
+    return [self setYLabels:yLabels withHeight:yLabelHeight];
+}
+
+- (void)setYLabels:(NSArray *)yLabels withHeight:(CGFloat)height {
+    _yLabels = yLabels;
+    _yLabelHeight = height;
+    if (_yChartLabels) {
+        for (PNChartLabel *label in _yChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _yChartLabels = [NSMutableArray new];
+    }
+
+    NSString *labelText;
+
+    if (_showLabel) {
+        CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+
+        for (int index = 0; index < yLabels.count; index++) {
+            labelText = yLabels[(NSUInteger) index];
+
+            NSInteger y = (NSInteger) (_chartCavanHeight + _chartMarginTop - index * yStepHeight);
+
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, y, (CGFloat) ((NSInteger) _chartMarginLeft * 0.9), (NSInteger) _yLabelHeight)];
+            [label setTextAlignment:NSTextAlignmentRight];
+            label.text = labelText;
+            [self setCustomStyleForYLabel:label];
+            [self addSubview:label];
+            [_yChartLabels addObject:label];
+        }
+    }
+}
+
+- (CGFloat)computeEqualWidthForXLabels:(NSArray *)xLabels {
+    CGFloat xLabelWidth;
+
+    if (_showLabel) {
+        xLabelWidth = _chartCavanWidth / [xLabels count];
+    } else {
+        xLabelWidth = (self.frame.size.width) / [xLabels count];
+    }
+
+    return xLabelWidth;
+}
+
+
+- (void)setXLabels:(NSArray *)xLabels {
+    CGFloat xLabelWidth;
+
+    if (_showLabel) {
+        xLabelWidth = _chartCavanWidth / [xLabels count];
+    } else {
+        xLabelWidth = (self.frame.size.width - _chartMarginLeft - _chartMarginRight) / [xLabels count];
+    }
+
+    return [self setXLabels:xLabels withWidth:xLabelWidth];
+}
+
+- (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width {
+    _xLabels = xLabels;
+    _xLabelWidth = width;
+    if (_xChartLabels) {
+        for (PNChartLabel *label in _xChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _xChartLabels = [NSMutableArray new];
+    }
+
+    NSString *labelText;
+
+    if (_showLabel) {
+        for (NSUInteger index = 0; index < xLabels.count; index++) {
+            labelText = xLabels[index];
+
+            NSInteger x = (NSInteger) (index * _xLabelWidth + _chartMarginLeft);
+            NSInteger y = (NSInteger) (_chartMarginBottom + _chartCavanHeight);
+
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(x, y, (NSInteger) _xLabelWidth, (NSInteger) _chartMarginBottom)];
+            [label setTextAlignment:NSTextAlignmentCenter];
+            label.text = labelText;
+            [self setCustomStyleForXLabel:label];
+            [self addSubview:label];
+            [_xChartLabels addObject:label];
+        }
+    }
+}
+
+- (void)setCustomStyleForXLabel:(UILabel *)label {
+    if (_xLabelFont) {
+        label.font = _xLabelFont;
+    }
+
+    if (_xLabelColor) {
+        label.textColor = _xLabelColor;
+    }
+
+}
+
+- (void)setCustomStyleForYLabel:(UILabel *)label {
+    if (_yLabelFont) {
+        label.font = _yLabelFont;
+    }
+
+    if (_yLabelColor) {
+        label.textColor = _yLabelColor;
+    }
+}
+
+#pragma mark - Touch at point
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+    [self touchPoint:touches withEvent:event];
+    [self touchKeyPoint:touches withEvent:event];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+    [self touchPoint:touches withEvent:event];
+    [self touchKeyPoint:touches withEvent:event];
+}
+
+- (void)touchPoint:(NSSet *)touches withEvent:(UIEvent *)event {
+    // Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+
+    for (NSUInteger p = 0; p < _pathPoints.count; p++) {
+        NSArray *linePointsArray = _endPointsOfPath[p];
+
+        for (NSUInteger i = 0; i < (int) linePointsArray.count - 1; i += 2) {
+            CGPoint p1 = [linePointsArray[i] CGPointValue];
+            CGPoint p2 = [linePointsArray[i + 1] CGPointValue];
+
+            // Closest distance from point to line
+            float distance = (float) fabs(((p2.x - p1.x) * (touchPoint.y - p1.y)) - ((p1.x - touchPoint.x) * (p1.y - p2.y)));
+            distance /= hypot(p2.x - p1.x, p1.y - p2.y);
+
+            if (distance <= 5.0) {
+                // Conform to delegate parameters, figure out what bezier path this CGPoint belongs to.
+                NSUInteger lineIndex = 0;
+                for (NSArray<UIBezierPath *> *paths in _chartPath) {
+                    for (UIBezierPath *path in paths) {
+                        BOOL pointContainsPath = CGPathContainsPoint(path.CGPath, NULL, p1, NO);
+                        if (pointContainsPath) {
+                            [_delegate userClickedOnLinePoint:touchPoint lineIndex:lineIndex];
+                            return;
+                        }
+                    }
+                    lineIndex++;
+                }
+            }
+        }
+    }
+}
+
+- (void)touchKeyPoint:(NSSet *)touches withEvent:(UIEvent *)event {
+    // Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+
+    for (NSUInteger p = 0; p < _pathPoints.count; p++) {
+        NSArray *linePointsArray = _pathPoints[p];
+
+        for (NSUInteger i = 0; i < (int) linePointsArray.count - 1; i += 1) {
+            CGPoint p1 = [linePointsArray[i] CGPointValue];
+            CGPoint p2 = [linePointsArray[i + 1] CGPointValue];
+
+            float distanceToP1 = (float) fabs(hypot(touchPoint.x - p1.x, touchPoint.y - p1.y));
+            float distanceToP2 = (float) hypot(touchPoint.x - p2.x, touchPoint.y - p2.y);
+
+            float distance = MIN(distanceToP1, distanceToP2);
+
+            if (distance <= 10.0) {
+                [_delegate userClickedOnLineKeyPoint:touchPoint
+                                           lineIndex:p
+                                          pointIndex:(distance == distanceToP2 ? i + 1 : i)];
+
+                return;
+            }
+        }
+    }
+}
+
+#pragma mark - Draw Chart
+
+- (void)populateChartLines {
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        NSArray<UIBezierPath *> *progressLines = self.chartPath[lineIndex];
+        // each chart line can be divided into multiple paths because
+        // we need ot draw each path with different color
+        // if there is not rangeColors then there is only one progressLinePath per chart
+        NSArray<UIColor *> *progressLineColors = self.progressLinePathsColors[lineIndex];
+        [self.chartLineArray[lineIndex] removeAllObjects];
+        NSUInteger progressLineIndex = 0;;
+        for (UIBezierPath *progressLinePath in progressLines) {
+            PNLineChartData *chartData = self.chartData[lineIndex];
+            CAShapeLayer *chartLine = [CAShapeLayer layer];
+            chartLine.lineCap = kCALineCapButt;
+            chartLine.lineJoin = kCALineJoinMiter;
+            chartLine.fillColor = self.backgroundColor.CGColor;
+            chartLine.lineWidth = chartData.lineWidth;
+            chartLine.path = progressLinePath.CGPath;
+            chartLine.strokeEnd = 0.0;
+            chartLine.strokeColor = progressLineColors[progressLineIndex].CGColor;
+            [self.layer addSublayer:chartLine];
+            [self.chartLineArray[lineIndex] addObject:chartLine];
+            progressLineIndex++;
+        }
+    }
+}
+
+/*
+ * strokeChart should remove the previously drawn chart lines and points
+ * and then proceed to draw the new lines
+ */
+- (void)strokeChart {
+    [self removeLayers];
+    // remove all shape layers before adding new ones
+    [self recreatePointLayers];
+    // Cavan height and width needs to be set before
+    // setNeedsDisplay is invoked because setNeedsDisplay
+    // will invoke drawRect and if Cavan dimensions is not
+    // set the chart will be misplaced
+    [self resetCavanHeight];
+    [self prepareYLabelsWithData:_chartData];
+
+    _chartPath = [[NSMutableArray alloc] init];
+    _pointPath = [[NSMutableArray alloc] init];
+    _gradeStringPaths = [NSMutableArray array];
+    _progressLinePathsColors = [[NSMutableArray alloc] init];
+
+    [self calculateChartPath:_chartPath
+               andPointsPath:_pointPath
+            andPathKeyPoints:_pathPoints
+       andPathStartEndPoints:_endPointsOfPath
+  andProgressLinePathsColors:_progressLinePathsColors];
+    [self populateChartLines];
+    // Draw each line
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        PNLineChartData *chartData = self.chartData[lineIndex];
+        NSArray<CAShapeLayer *> *chartLines =self.chartLineArray[lineIndex];
+        CAShapeLayer *pointLayer = (CAShapeLayer *) self.chartPointArray[lineIndex];
+        UIGraphicsBeginImageContext(self.frame.size);
+        if (chartData.inflexionPointColor) {
+            pointLayer.strokeColor = [[chartData.inflexionPointColor
+                    colorWithAlphaComponent:chartData.alpha] CGColor];
+        } else {
+            pointLayer.strokeColor = [PNGreen CGColor];
+        }
+        // setup the color of the chart line
+        NSArray<UIBezierPath *> *progressLines = _chartPath[lineIndex];
+        UIBezierPath *pointPath = _pointPath[lineIndex];
+
+        pointLayer.path = pointPath.CGPath;
+
+        [CATransaction begin];
+        for (NSUInteger index = 0; index < progressLines.count; index++) {
+            CAShapeLayer *chartLine = chartLines[index];
+            //chartLine strokeColor is already set. no need to override here
+            [chartLine addAnimation:self.pathAnimation forKey:@"strokeEndAnimation"];
+            chartLine.strokeEnd = 1.0;
+        }
+
+        // if you want cancel the point animation, comment this code, the point will show immediately
+        if (chartData.inflexionPointStyle != PNLineChartPointStyleNone) {
+            [pointLayer addAnimation:self.pathAnimation forKey:@"strokeEndAnimation"];
+        }
+
+        [CATransaction commit];
+
+        NSMutableArray *textLayerArray = self.gradeStringPaths[lineIndex];
+        for (CATextLayer *textLayer in textLayerArray) {
+            CABasicAnimation *fadeAnimation = [self fadeAnimation];
+            [textLayer addAnimation:fadeAnimation forKey:nil];
+        }
+
+        UIGraphicsEndImageContext();
+    }
+    [self setNeedsDisplay];
+}
+
+
+- (void)calculateChartPath:(NSMutableArray *)chartPath
+             andPointsPath:(NSMutableArray *)pointsPath
+          andPathKeyPoints:(NSMutableArray *)pathPoints
+     andPathStartEndPoints:(NSMutableArray *)pointsOfPath
+andProgressLinePathsColors:(NSMutableArray *)progressLinePathsColors {
+
+    // Draw each line
+
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        PNLineChartData *chartData = self.chartData[lineIndex];
+
+        CGFloat yValue;
+        NSMutableArray<UIBezierPath *> *progressLines = [NSMutableArray new];
+        NSMutableArray<UIColor *> *progressLineColors = [NSMutableArray new];
+
+        UIBezierPath *pointPath = [UIBezierPath bezierPath];
+
+
+        [chartPath insertObject:progressLines atIndex:lineIndex];
+        [pointsPath insertObject:pointPath atIndex:lineIndex];
+        [progressLinePathsColors insertObject:progressLineColors atIndex:lineIndex];
+
+
+        NSMutableArray *gradePathArray = [NSMutableArray array];
+        [self.gradeStringPaths addObject:gradePathArray];
+
+        NSMutableArray *linePointsArray = [[NSMutableArray alloc] init];
+        NSMutableArray *lineStartEndPointsArray = [[NSMutableArray alloc] init];
+        int last_x = 0;
+        int last_y = 0;
+        NSMutableArray<NSDictionary<NSString *, NSValue *> *> *progressLinePaths = [NSMutableArray new];
+        UIColor *defaultColor = chartData.color != nil ? chartData.color : [UIColor greenColor];
+        CGFloat inflexionWidth = chartData.inflexionPointWidth;
+
+        for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+
+            NSValue *from = nil;
+            NSValue *to = nil;
+
+            yValue = chartData.getData(i).y;
+
+            int x = (int) (i * _xLabelWidth + _chartMarginLeft + _xLabelWidth / 2.0);
+            int y = (int)[self yValuePositionInLineChart:yValue];
+
+            // Circular point
+            if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle)
+            {
+
+                CGRect circleRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+                CGPoint circleCenter = CGPointMake(circleRect.origin.x + (circleRect.size.width / 2), circleRect.origin.y + (circleRect.size.height / 2));
+
+                [pointPath moveToPoint:CGPointMake(circleCenter.x + (inflexionWidth / 2), circleCenter.y)];
+                [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:(CGFloat) (2 * M_PI) clockwise:YES];
+
+                //jet text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:circleCenter width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+
+                    // calculate the point for line
+                    float distance = (float) sqrt(pow(x - last_x, 2) + pow(y - last_y, 2));
+                    float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2) / distance * (x - last_x);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            }
+                // Square point
+            else if (chartData.inflexionPointStyle == PNLineChartPointStyleSquare) {
+
+                CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+                CGPoint squareCenter = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y + (squareRect.size.height / 2));
+
+                [pointPath moveToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
+                [pointPath closePath];
+
+                // text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:squareCenter width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+
+                    // calculate the point for line
+                    float distance = (float) sqrt(pow(x - last_x, 2) + pow(y - last_y, 2));
+                    float last_x1 = last_x + (inflexionWidth / 2);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            }
+                // Triangle point
+            else if (chartData.inflexionPointStyle == PNLineChartPointStyleTriangle) {
+
+                CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+
+                CGPoint startPoint = CGPointMake(squareRect.origin.x, squareRect.origin.y + squareRect.size.height);
+                CGPoint endPoint = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y);
+                CGPoint middlePoint = CGPointMake(squareRect.origin.x + (squareRect.size.width), squareRect.origin.y + squareRect.size.height);
+
+                [pointPath moveToPoint:startPoint];
+                [pointPath addLineToPoint:middlePoint];
+                [pointPath addLineToPoint:endPoint];
+                [pointPath closePath];
+
+                // text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:middlePoint width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+                    // calculate the point for triangle
+                    float distance = (float) (sqrt(pow(x - last_x, 2) + pow(y - last_y, 2)) * 1.4);
+                    float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2) / distance * (x - last_x);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            } else {
+
+                if (i > 0) {
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x, last_y)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x, y)];
+                }
+            }
+            if(from != nil && to != nil) {
+                [progressLinePaths addObject:@{@"from": from,  @"to":to}];
+                [lineStartEndPointsArray addObject:from];
+                [lineStartEndPointsArray addObject:to];
+            }
+            [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];
+            last_x = x;
+            last_y = y;
+        }
+
+        [pointsOfPath addObject:[lineStartEndPointsArray copy]];
+        [pathPoints addObject:[linePointsArray copy]];
+        // if rangeColors is not nil then it means we need to draw the chart
+        // with different colors. colorRangesBetweenP1.. function takes care of
+        // partitioning the p1->p2 into segments from which we can create UIBezierPath
+        if (self.showSmoothLines && chartData.itemCount >= 4) {
+            for (NSDictionary<NSString *, NSValue *> *item in progressLinePaths) {
+                NSArray<NSDictionary *> *calculatedRanges =
+                        [self colorRangesBetweenP1:[item[@"from"] CGPointValue]
+                                                P2:[item[@"to"] CGPointValue]
+                                       rangeColors:chartData.rangeColors
+                                      defaultColor:defaultColor];
+                for (NSDictionary *range in calculatedRanges) {
+//                    NSLog(@"range : %@ range: %@ color %@", range[@"from"], range[@"to"], range[@"color"]);
+                    UIBezierPath *currentProgressLine = [UIBezierPath bezierPath];
+                    CGPoint segmentP1 = [range[@"from"] CGPointValue];
+                    CGPoint segmentP2 = [range[@"to"] CGPointValue];
+                    [currentProgressLine moveToPoint:segmentP1];
+                    CGPoint midPoint = [PNLineChart midPointBetweenPoint1:segmentP1 andPoint2:segmentP2];
+                    [currentProgressLine addQuadCurveToPoint:midPoint
+                                                controlPoint:[PNLineChart controlPointBetweenPoint1:midPoint andPoint2:segmentP1]];
+                    [currentProgressLine addQuadCurveToPoint:segmentP2
+                                                controlPoint:[PNLineChart controlPointBetweenPoint1:midPoint andPoint2:segmentP2]];
+                    [progressLines addObject:currentProgressLine];
+                    [progressLineColors addObject:range[@"color"]];
+                }
+            }
+        } else {
+            for (NSDictionary<NSString *, NSValue *> *item in progressLinePaths) {
+                NSArray<NSDictionary *> *calculatedRanges =
+                        [self colorRangesBetweenP1:[item[@"from"] CGPointValue]
+                                                P2:[item[@"to"] CGPointValue]
+                                       rangeColors:chartData.rangeColors
+                                      defaultColor:defaultColor];
+                for (NSDictionary *range in calculatedRanges) {
+//                    NSLog(@"range : %@ range: %@ color %@", range[@"from"], range[@"to"], range[@"color"]);
+                    UIBezierPath *currentProgressLine = [UIBezierPath bezierPath];
+                    [currentProgressLine moveToPoint:[range[@"from"] CGPointValue]];
+                    [currentProgressLine addLineToPoint:[range[@"to"] CGPointValue]];
+                    [progressLines addObject:currentProgressLine];
+                    [progressLineColors addObject:range[@"color"]];
+                }
+            }
+        }
+    }
+}
+
+#pragma mark - Set Chart Data
+
+- (void)setChartData:(NSArray *)data {
+    if (data != _chartData) {
+        _chartData = data;
+    }
+}
+
+
+- (void)removeLayers {
+    for (NSArray<CALayer *> *layers in self.chartLineArray) {
+        for (CALayer *layer in layers) {
+            [layer removeFromSuperlayer];
+        }
+    }
+    for (CALayer *layer in self.chartPointArray) {
+        [layer removeFromSuperlayer];
+    }
+    self.chartLineArray = [NSMutableArray arrayWithCapacity:_chartData.count];
+    self.chartPointArray = [NSMutableArray arrayWithCapacity:_chartData.count];
+}
+
+-(void) resetCavanHeight {
+    _chartCavanHeight = self.frame.size.height - _chartMarginBottom - _chartMarginTop;
+    if (!_showLabel) {
+        _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight;
+        _chartCavanWidth = self.frame.size.width;
+        //_chartMargin = chartData.inflexionPointWidth;
+        _xLabelWidth = (_chartCavanWidth / ([_xLabels count]));
+    }
+}
+
+- (void)recreatePointLayers {
+    for (PNLineChartData *chartData in _chartData) {
+        // create as many chart line layers as there are data-lines
+        [self.chartLineArray addObject:[NSMutableArray new]];
+
+        // create point
+        CAShapeLayer *pointLayer = [CAShapeLayer layer];
+        pointLayer.strokeColor = [[chartData.color colorWithAlphaComponent:chartData.alpha] CGColor];
+        pointLayer.lineCap = kCALineCapRound;
+        pointLayer.lineJoin = kCALineJoinBevel;
+        pointLayer.fillColor = nil;
+        pointLayer.lineWidth = chartData.lineWidth;
+        [self.layer addSublayer:pointLayer];
+        [self.chartPointArray addObject:pointLayer];
+    }
+}
+
+- (void)prepareYLabelsWithData:(NSArray *)data {
+    CGFloat yMax = 0.0f;
+    CGFloat yMin = MAXFLOAT;
+    NSMutableArray *yLabelsArray = [NSMutableArray new];
+
+    for (PNLineChartData *chartData in data) {
+        // create as many chart line layers as there are data-lines
+
+        for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+            CGFloat yValue = chartData.getData(i).y;
+            [yLabelsArray addObject:[NSString stringWithFormat:@"%2f", yValue]];
+            yMax = fmaxf(yMax, yValue);
+            yMin = fminf(yMin, yValue);
+        }
+    }
+
+
+    if (_yValueMin == -FLT_MAX) {
+        _yValueMin = (_yFixedValueMin > -FLT_MAX) ? _yFixedValueMin : yMin;
+    }
+    if (_yValueMax == -FLT_MAX) {
+        _yValueMax = (CGFloat) ((_yFixedValueMax > -FLT_MAX) ? _yFixedValueMax : yMax + yMax / 10.0);
+    }
+
+    if (_showGenYLabels) {
+        [self setYLabels];
+    }
+
+}
+
+#pragma mark - Update Chart Data
+
+- (void)updateChartData:(NSArray *)data {
+    _chartData = data;
+
+    [self prepareYLabelsWithData:data];
+
+    [self calculateChartPath:_chartPath
+               andPointsPath:_pointPath
+            andPathKeyPoints:_pathPoints
+       andPathStartEndPoints:_endPointsOfPath
+  andProgressLinePathsColors:_progressLinePathsColors];
+
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+
+        CAShapeLayer *chartLine = (CAShapeLayer *) self.chartLineArray[lineIndex];
+        CAShapeLayer *pointLayer = (CAShapeLayer *) self.chartPointArray[lineIndex];
+
+
+        NSArray<UIBezierPath *> *progressLines = _chartPath[lineIndex];
+        UIBezierPath *pointPath = _pointPath[lineIndex];
+
+        for(UIBezierPath *progressLine in progressLines) {
+            CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+            pathAnimation.fromValue = (id) chartLine.path;
+            pathAnimation.toValue = (__bridge id) [progressLine CGPath];
+            pathAnimation.duration = 0.5f;
+            pathAnimation.autoreverses = NO;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            [chartLine addAnimation:pathAnimation forKey:@"animationKey"];
+            chartLine.path = progressLine.CGPath;
+        }
+
+        CABasicAnimation *pointPathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+        pointPathAnimation.fromValue = (id) pointLayer.path;
+        pointPathAnimation.toValue = (__bridge id) [pointPath CGPath];
+        pointPathAnimation.duration = 0.5f;
+        pointPathAnimation.autoreverses = NO;
+        pointPathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        [pointLayer addAnimation:pointPathAnimation forKey:@"animationKey"];
+
+        pointLayer.path = pointPath.CGPath;
+
+
+    }
+
+}
+
+#define IOS7_OR_LATER [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0
+
+- (void)drawRect:(CGRect)rect {
+    if (self.isShowCoordinateAxis) {
+        CGFloat yAxisOffset = 10.f;
+
+        CGContextRef ctx = UIGraphicsGetCurrentContext();
+        UIGraphicsPopContext();
+        UIGraphicsPushContext(ctx);
+        CGContextSetLineWidth(ctx, self.axisWidth);
+        CGContextSetStrokeColorWithColor(ctx, [self.axisColor CGColor]);
+
+        CGFloat xAxisWidth = CGRectGetWidth(rect) - (_chartMarginLeft + _chartMarginRight) / 2;
+        CGFloat yAxisHeight = _chartMarginBottom + _chartCavanHeight;
+
+        // draw coordinate axis
+        CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset, 0);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, yAxisHeight);
+        CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight);
+        CGContextStrokePath(ctx);
+
+        // draw y axis arrow
+        CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset - 3, 6);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, 0);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset + 3, 6);
+        CGContextStrokePath(ctx);
+
+        // draw x axis arrow
+        CGContextMoveToPoint(ctx, xAxisWidth - 6, yAxisHeight - 3);
+        CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight);
+        CGContextAddLineToPoint(ctx, xAxisWidth - 6, yAxisHeight + 3);
+        CGContextStrokePath(ctx);
+
+        if (self.showLabel) {
+
+            // draw x axis separator
+            CGPoint point;
+            for (NSUInteger i = 0; i < [self.xLabels count]; i++) {
+                point = CGPointMake(2 * _chartMarginLeft + (i * _xLabelWidth), _chartMarginBottom + _chartCavanHeight);
+                CGContextMoveToPoint(ctx, point.x, point.y - 2);
+                CGContextAddLineToPoint(ctx, point.x, point.y);
+                CGContextStrokePath(ctx);
+            }
+
+            // draw y axis separator
+            CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+            for (NSUInteger i = 0; i < [self.xLabels count]; i++) {
+                point = CGPointMake(_chartMarginBottom + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2));
+                CGContextMoveToPoint(ctx, point.x, point.y);
+                CGContextAddLineToPoint(ctx, point.x + 2, point.y);
+                CGContextStrokePath(ctx);
+            }
+        }
+
+        UIFont *font = [UIFont systemFontOfSize:11];
+
+        // draw y unit
+        if ([self.yUnit length]) {
+            CGFloat height = [PNLineChart sizeOfString:self.yUnit withWidth:30.f font:font].height;
+            CGRect drawRect = CGRectMake(_chartMarginLeft + 10 + 5, 0, 30.f, height);
+            [self drawTextInContext:ctx text:self.yUnit inRect:drawRect font:font color:self.yLabelColor];
+        }
+
+        // draw x unit
+        if ([self.xUnit length]) {
+            CGFloat height = [PNLineChart sizeOfString:self.xUnit withWidth:30.f font:font].height;
+            CGRect drawRect = CGRectMake(CGRectGetWidth(rect) - _chartMarginLeft + 5, _chartMarginBottom + _chartCavanHeight - height / 2, 25.f, height);
+            [self drawTextInContext:ctx text:self.xUnit inRect:drawRect font:font color:self.xLabelColor];
+        }
+    }
+    if (self.showYGridLines) {
+        CGContextRef ctx = UIGraphicsGetCurrentContext();
+        CGFloat yAxisOffset = _showLabel ? 10.f : 0.0f;
+        CGPoint point;
+        CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+        if (self.yGridLinesColor) {
+            CGContextSetStrokeColorWithColor(ctx, self.yGridLinesColor.CGColor);
+        } else {
+            CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);
+        }
+        for (NSUInteger i = 0; i < _yLabelNum; i++) {
+            point = CGPointMake(_chartMarginLeft + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2));
+            CGContextMoveToPoint(ctx, point.x, point.y);
+            // add dotted style grid
+            CGFloat dash[] = {6, 5};
+            // dot diameter is 20 points
+            CGContextSetLineWidth(ctx, 0.5);
+            CGContextSetLineCap(ctx, kCGLineCapRound);
+            CGContextSetLineDash(ctx, 0.0, dash, 2);
+            CGContextAddLineToPoint(ctx, CGRectGetWidth(rect) - _chartMarginLeft + 5, point.y);
+            CGContextStrokePath(ctx);
+        }
+    }
+
+    [super drawRect:rect];
+}
+
+#pragma mark private methods
+
+/*
+ * helper function that maps a y value ( from chartData) to
+ * a position in the chart ( between _yValueMin and _yValueMax)
+ */
+- (CGFloat)yValuePositionInLineChart:(CGFloat)y {
+    CGFloat innerGrade;
+    if (!(_yValueMax - _yValueMin)) {
+        innerGrade = 0.5;
+    } else {
+        innerGrade = ((CGFloat) y - _yValueMin) / (_yValueMax - _yValueMin);
+    }
+    return _chartCavanHeight - (innerGrade * _chartCavanHeight) - (_yLabelHeight / 2) + _chartMarginTop;
+}
+
+/**
+ * return array of segments which represents the color and path
+ * for each segments.
+ * for instance if p1.y=1 and p2.y=10
+ * and rangeColor = use blue for 2<y<3 and red for 4<y<6
+ * then this function divides the space between p1 and p2 into three segments
+ *  segment #1 : 1-2 : default color
+ *  segment #2 : 2-3 : blue
+ *  segment #3 : 3-4 : default color
+ *  segment #4 : 4-6 : red
+ *  segment #5: 6-10 : default color
+ *
+ *  keep in mind that the rangeColors values are based on the chartData so it needs to
+ *  convert those values to coordinates which are valid between yValueMin and yValueMax
+ *
+ *  in order to find whether there is an overlap between any of the rangeColors and the
+ *  p1-p2 it uses NSIntersectionRange to intersect their yValues.
+ *
+ * @param p1
+ * @param p2
+ * @param rangeColors
+ * @param defaultColor
+ * @return
+ */
+- (NSArray *)colorRangesBetweenP1:(CGPoint)p1 P2:(CGPoint)p2
+                      rangeColors:(NSArray<PNLineChartColorRange *> *)rangeColors
+                     defaultColor:(UIColor *)defaultColor {
+    if (rangeColors && rangeColors.count > 0 && p2.x > p1.x) {
+        PNLineChartColorRange *colorForRangeInfo = [[rangeColors firstObject] copy];
+        NSArray *remainingRanges = nil;
+        if (rangeColors.count > 1) {
+            remainingRanges = [rangeColors subarrayWithRange:NSMakeRange(1, rangeColors.count - 1)];
+        }
+        // tRange : convert the rangeColors.range values to value between yValueMin and yValueMax
+        CGFloat transformedStart = [self yValuePositionInLineChart:(CGFloat)
+                colorForRangeInfo.range.location];
+        CGFloat transformedEnd = [self yValuePositionInLineChart:(CGFloat)
+                (colorForRangeInfo.range.location + colorForRangeInfo.range.length)];
+
+        NSRange pathRange = NSMakeRange((NSUInteger) fmin(p1.y, p2.y), (NSUInteger) fabs(p2.y - p1.y));
+        NSRange tRange = NSMakeRange((NSUInteger) fmin(transformedStart, transformedEnd),
+                (NSUInteger) fabs(transformedEnd - transformedStart));
+        if (NSIntersectionRange(tRange, pathRange).length > 0) {
+            CGPoint partition1EndPoint;
+            CGPoint partition2EndPoint;
+            NSArray *partition1 = @[];
+            NSDictionary *partition2 = nil;
+            NSArray *partition3 = @[];
+            if (p2.y >= p1.y) {
+                partition1EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmax(p1.y, tRange.location)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmax(p1.y, tRange.location));
+                partition2EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmin(p2.y, tRange.location + tRange.length)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmin(p2.y, tRange.location + tRange.length));
+            } else {
+                partition1EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmin(p1.y, tRange.location + tRange.length)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmin(p1.y, tRange.location + tRange.length));
+                partition2EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmax(p2.y, tRange.location)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmax(p2.y, tRange.location));
+            }
+            if (p1.y != partition1EndPoint.y) {
+                partition1 = [self colorRangesBetweenP1:p1
+                                                     P2:partition1EndPoint
+                                            rangeColors:remainingRanges
+                                           defaultColor:defaultColor];
+            }
+            partition2 = @{
+                    @"color": colorForRangeInfo.color,
+                    @"from": [NSValue valueWithCGPoint:partition1EndPoint],
+                    @"to": [NSValue valueWithCGPoint:partition2EndPoint]};
+            if (p2.y != partition2EndPoint.y) {
+                partition3 = [self colorRangesBetweenP1:partition2EndPoint
+                                                     P2:p2
+                                            rangeColors:remainingRanges
+                                           defaultColor:defaultColor];
+            }
+            return [[partition1 arrayByAddingObject:partition2] arrayByAddingObjectsFromArray:partition3];
+        } else {
+
+            return [self colorRangesBetweenP1:p1
+                                           P2:p2
+                                  rangeColors:remainingRanges
+                                 defaultColor:defaultColor];
+        }
+    } else {
+        return @[@{
+                @"color": defaultColor,
+                @"from": [NSValue valueWithCGPoint:p1],
+                @"to": [NSValue valueWithCGPoint:p2]}];
+    }
+}
+
+
+- (void)setupDefaultValues {
+    [super setupDefaultValues];
+    // Initialization code
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds = YES;
+    self.chartLineArray = [NSMutableArray new];
+    _showLabel = YES;
+    _showGenYLabels = YES;
+    _pathPoints = [[NSMutableArray alloc] init];
+    _endPointsOfPath = [[NSMutableArray alloc] init];
+    self.userInteractionEnabled = YES;
+
+    _yFixedValueMin = -FLT_MAX;
+    _yFixedValueMax = -FLT_MAX;
+    _yValueMax = -FLT_MAX;
+    _yValueMin = -FLT_MAX;
+    _yLabelNum = 5;
+    _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize];
+
+//    _chartMargin = 40;
+
+    _chartMarginLeft = 25.0;
+    _chartMarginRight = 25.0;
+    _chartMarginTop = 25.0;
+    _chartMarginBottom = 25.0;
+
+    _yLabelFormat = @"%1.f";
+
+    _chartCavanWidth = self.frame.size.width - _chartMarginLeft - _chartMarginRight;
+    _chartCavanHeight = self.frame.size.height - _chartMarginBottom - _chartMarginTop;
+
+    // Coordinate Axis Default Values
+    _showCoordinateAxis = NO;
+    _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f];
+    _axisWidth = 1.f;
+
+    // do not create curved line chart by default
+    _showSmoothLines = NO;
+
+}
+
+#pragma mark - tools
+
++ (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font {
+    CGSize size = CGSizeMake(width, MAXFLOAT);
+
+    if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
+        NSDictionary *tdic = @{NSFontAttributeName: font};
+        size = [text boundingRectWithSize:size
+                                  options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
+                               attributes:tdic
+                                  context:nil].size;
+    } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        size = [text sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByCharWrapping];
+#pragma clang diagnostic pop
+    }
+
+    return size;
+}
+
++ (CGPoint)midPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    return CGPointMake((point1.x + point2.x) / 2, (point1.y + point2.y) / 2);
+}
+
++ (CGFloat)xOfY:(CGFloat)y betweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    CGFloat m = (point2.y - point1.y) / (point2.x - point1.x);
+    // formulate = y - y1 = m (x - x1) = mx - mx1 -> mx = y - y1 + mx1 ->
+    // x = (y - y1 + mx1) / m
+    return (y - point1.y + m * point1.x) / m;
+}
+
+
++ (CGPoint)controlPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    CGPoint controlPoint = [self midPointBetweenPoint1:point1 andPoint2:point2];
+    CGFloat diffY = abs((int) (point2.y - controlPoint.y));
+    if (point1.y < point2.y)
+        controlPoint.y += diffY;
+    else if (point1.y > point2.y)
+        controlPoint.y -= diffY;
+    return controlPoint;
+}
+
+- (void)drawTextInContext:(CGContextRef)ctx text:(NSString *)text inRect:(CGRect)rect font:(UIFont *)font color:(UIColor *)color {
+    if (IOS7_OR_LATER) {
+        NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+        priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
+        priceParagraphStyle.alignment = NSTextAlignmentLeft;
+
+        if (color != nil) {
+            [text drawInRect:rect
+              withAttributes:@{NSParagraphStyleAttributeName: priceParagraphStyle, NSFontAttributeName: font,
+                      NSForegroundColorAttributeName: color}];
+        } else {
+            [text drawInRect:rect
+              withAttributes:@{NSParagraphStyleAttributeName: priceParagraphStyle, NSFontAttributeName: font}];
+        }
+    } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        [text drawInRect:rect
+                withFont:font
+           lineBreakMode:NSLineBreakByTruncatingTail
+               alignment:NSTextAlignmentLeft];
+#pragma clang diagnostic pop
+    }
+}
+
+- (NSString *)formatYLabel:(double)value {
+
+    if (self.yLabelBlockFormatter) {
+        return self.yLabelBlockFormatter((CGFloat) value);
+    } else {
+        if (!self.thousandsSeparator) {
+            NSString *format = self.yLabelFormat ?: @"%1.f";
+            return [NSString stringWithFormat:format, value];
+        }
+
+        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
+        [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
+        [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
+        return [numberFormatter stringFromNumber:@(value)];
+    }
+}
+
+- (UIView *)getLegendWithMaxWidth:(CGFloat)mWidth {
+    if ([self.chartData count] < 1) {
+        return nil;
+    }
+
+    /* This is a short line that refers to the chart data */
+    CGFloat legendLineWidth = 40;
+
+    /* x and y are the coordinates of the starting point of each legend item */
+    CGFloat x = 0;
+    CGFloat y = 0;
+
+    /* accumulated height */
+    CGFloat totalHeight = 0;
+    CGFloat totalWidth = 0;
+
+    NSMutableArray *legendViews = [[NSMutableArray alloc] init];
+
+    /* Determine the max width of each legend item */
+    CGFloat maxLabelWidth;
+    if (self.legendStyle == PNLegendItemStyleStacked) {
+        maxLabelWidth = mWidth - legendLineWidth;
+    } else {
+        maxLabelWidth = MAXFLOAT;
+    }
+
+    /* this is used when labels wrap text and the line
+     * should be in the middle of the first row */
+    CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test"
+                                              withWidth:MAXFLOAT
+                                                   font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height;
+
+    NSUInteger counter = 0;
+    NSUInteger rowWidth = 0;
+    NSUInteger rowMaxHeight = 0;
+
+    for (PNLineChartData *pdata in self.chartData) {
+        /* Expected label size*/
+        CGSize labelsize = [PNLineChart sizeOfString:pdata.dataTitle
+                                           withWidth:maxLabelWidth
+                                                font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]];
+
+        /* draw lines */
+        if ((rowWidth + labelsize.width + legendLineWidth > mWidth) && (self.legendStyle == PNLegendItemStyleSerial)) {
+            rowWidth = 0;
+            x = 0;
+            y += rowMaxHeight;
+            rowMaxHeight = 0;
+        }
+        rowWidth += labelsize.width + legendLineWidth;
+        totalWidth = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(rowWidth, totalWidth) : fmaxf(totalWidth, labelsize.width + legendLineWidth);
+
+        /* If there is inflection decorator, the line is composed of two lines
+         * and this is the space that separates two lines in order to put inflection
+         * decorator */
+
+        CGFloat inflexionWidthSpacer = pdata.inflexionPointStyle == PNLineChartPointStyleTriangle ? pdata.inflexionPointWidth / 2 : pdata.inflexionPointWidth;
+
+        CGFloat halfLineLength;
+
+        if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) {
+            halfLineLength = (CGFloat) ((legendLineWidth * 0.8 - inflexionWidthSpacer) / 2);
+        } else {
+            halfLineLength = (CGFloat) (legendLineWidth * 0.8);
+        }
+
+        UIView *line = [[UIView alloc] initWithFrame:CGRectMake((CGFloat) (x + legendLineWidth * 0.1), y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)];
+
+        line.backgroundColor = pdata.color;
+        line.alpha = pdata.alpha;
+        [legendViews addObject:line];
+
+        if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) {
+            line = [[UIView alloc] initWithFrame:CGRectMake((CGFloat) (x + legendLineWidth * 0.1 + halfLineLength + inflexionWidthSpacer), y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)];
+            line.backgroundColor = pdata.color;
+            line.alpha = pdata.alpha;
+            [legendViews addObject:line];
+        }
+
+        // Add inflexion type
+        UIColor *inflexionPointColor = pdata.inflexionPointColor;
+        if (!inflexionPointColor) {
+            inflexionPointColor = pdata.color;
+        }
+        [legendViews addObject:[self drawInflexion:pdata.inflexionPointWidth
+                                            center:CGPointMake(x + legendLineWidth / 2, y + singleRowHeight / 2)
+                                       strokeWidth:pdata.lineWidth
+                                    inflexionStyle:pdata.inflexionPointStyle
+                                          andColor:inflexionPointColor
+                                          andAlpha:pdata.alpha]];
+
+        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, labelsize.width, labelsize.height)];
+        label.text = pdata.dataTitle;
+        label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor];
+        label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f];
+        label.lineBreakMode = NSLineBreakByWordWrapping;
+        label.numberOfLines = 0;
+
+        rowMaxHeight = (NSUInteger) fmaxf(rowMaxHeight, labelsize.height);
+        x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth;
+        y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0;
+
+
+        totalHeight = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height;
+
+        [legendViews addObject:label];
+        counter++;
+    }
+
+    UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, mWidth, totalHeight)];
+
+    for (UIView *v in legendViews) {
+        [legend addSubview:v];
+    }
+    return legend;
+}
+
+
+- (UIImageView *)drawInflexion:(CGFloat)size center:(CGPoint)center strokeWidth:(CGFloat)sw inflexionStyle:(PNLineChartPointStyle)type andColor:(UIColor *)color andAlpha:(CGFloat)alfa {
+    //Make the size a little bigger so it includes also border stroke
+    CGSize aSize = CGSizeMake(size + sw, size + sw);
+
+
+    UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+
+
+    if (type == PNLineChartPointStyleCircle) {
+        CGContextAddArc(context, (size + sw) / 2, (size + sw) / 2, size / 2, 0, (CGFloat) (M_PI * 2), YES);
+    } else if (type == PNLineChartPointStyleSquare) {
+        CGContextAddRect(context, CGRectMake(sw / 2, sw / 2, size, size));
+    } else if (type == PNLineChartPointStyleTriangle) {
+        CGContextMoveToPoint(context, sw / 2, size + sw / 2);
+        CGContextAddLineToPoint(context, size + sw / 2, size + sw / 2);
+        CGContextAddLineToPoint(context, size / 2 + sw / 2, sw / 2);
+        CGContextAddLineToPoint(context, sw / 2, size + sw / 2);
+        CGContextClosePath(context);
+    }
+
+    //Set some stroke properties
+    CGContextSetLineWidth(context, sw);
+    CGContextSetAlpha(context, alfa);
+    CGContextSetStrokeColorWithColor(context, color.CGColor);
+
+    //Finally draw
+    CGContextDrawPath(context, kCGPathStroke);
+
+    //now get the image from the context
+    UIImage *squareImage = UIGraphicsGetImageFromCurrentImageContext();
+
+    UIGraphicsEndImageContext();
+
+    //// Translate origin
+    CGFloat originX = (CGFloat) (center.x - (size + sw) / 2.0);
+    CGFloat originY = (CGFloat) (center.y - (size + sw) / 2.0);
+
+    UIImageView *squareImageView = [[UIImageView alloc] initWithImage:squareImage];
+    [squareImageView setFrame:CGRectMake(originX, originY, size + sw, size + sw)];
+    return squareImageView;
+}
+
+#pragma mark setter and getter
+
+- (CATextLayer *)createPointLabelFor:(CGFloat)grade pointCenter:(CGPoint)pointCenter width:(CGFloat)width withChartData:(PNLineChartData *)chartData {
+    CATextLayer *textLayer = [[CATextLayer alloc] init];
+    [textLayer setAlignmentMode:kCAAlignmentCenter];
+    [textLayer setForegroundColor:[chartData.pointLabelColor CGColor]];
+    [textLayer setBackgroundColor:self.backgroundColor.CGColor];
+//    [textLayer setBackgroundColor:[self.backgroundColor colorWithAlphaComponent:0.8].CGColor];
+//    [textLayer setCornerRadius:(CGFloat) (textLayer.fontSize / 8.0)];
+
+    if (chartData.pointLabelFont != nil) {
+        [textLayer setFont:(__bridge CFTypeRef) (chartData.pointLabelFont)];
+        textLayer.fontSize = [chartData.pointLabelFont pointSize];
+    }
+
+    CGFloat textHeight = (CGFloat) (textLayer.fontSize * 1.1);
+    // FIXME: convert the grade to string and use its length instead of hardcoding 8
+    CGFloat textWidth = width * 8;
+    CGFloat textStartPosY;
+
+    textStartPosY = pointCenter.y - textLayer.fontSize;
+
+    [self.layer addSublayer:textLayer];
+
+    if (chartData.pointLabelFormat != nil) {
+        [textLayer setString:[[NSString alloc] initWithFormat:chartData.pointLabelFormat, grade]];
+    } else {
+        [textLayer setString:[[NSString alloc] initWithFormat:_yLabelFormat, grade]];
+    }
+
+    [textLayer setFrame:CGRectMake(0, 0, textWidth, textHeight)];
+    [textLayer setPosition:CGPointMake(pointCenter.x, textStartPosY)];
+    textLayer.contentsScale = [UIScreen mainScreen].scale;
+
+    return textLayer;
+}
+
+- (CABasicAnimation *)fadeAnimation {
+    CABasicAnimation *fadeAnimation = nil;
+    if (self.displayAnimated) {
+        fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeAnimation.fromValue = @0.0F;
+        fadeAnimation.toValue = @1.0F;
+        fadeAnimation.duration = 2.0;
+    }
+    return fadeAnimation;
+}
+
+- (CABasicAnimation *)pathAnimation {
+    if (self.displayAnimated && !_pathAnimation) {
+        _pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        _pathAnimation.duration = 1.0;
+        _pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        _pathAnimation.fromValue = @0.0f;
+        _pathAnimation.toValue = @1.0f;
+    }
+    if(!self.displayAnimated) {
+        _pathAnimation = nil;
+    }
+    return _pathAnimation;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChartData.h b/PNChartdemo/PNChart/PNLineChartData.h
new file mode 100755
index 0000000..2158e8e
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChartData.h
@@ -0,0 +1,61 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNLineChartPointStyle) {
+    PNLineChartPointStyleNone = 0,
+    PNLineChartPointStyleCircle = 1,
+    PNLineChartPointStyleSquare = 3,
+    PNLineChartPointStyleTriangle = 4
+};
+
+@class PNLineChartDataItem;
+
+typedef PNLineChartDataItem *(^LCLineChartDataGetter)(NSUInteger item);
+
+@interface PNLineChartColorRange : NSObject<NSCopying>
+
+@property(nonatomic) NSRange range;
+@property(nonatomic) BOOL inclusive;
+@property(nonatomic, retain) UIColor *color;
+
+- (id)initWithRange:(NSRange)range color:(UIColor *)color;
+
+@end
+
+@interface PNLineChartData : NSObject
+
+@property (strong) UIColor *color;
+@property (nonatomic) CGFloat alpha;
+@property NSUInteger itemCount;
+@property (copy) LCLineChartDataGetter getData;
+@property (strong, nonatomic) NSString *dataTitle;
+
+@property (nonatomic) BOOL showPointLabel;
+@property (nonatomic) UIColor *pointLabelColor;
+@property (nonatomic) UIFont *pointLabelFont;
+@property (nonatomic) NSString *pointLabelFormat;
+
+@property (nonatomic, assign) PNLineChartPointStyle inflexionPointStyle;
+@property (nonatomic) UIColor *inflexionPointColor;
+
+/**
+ * if rangeColor is set and the lineChartData values are within any
+ * of the given range then use the rangeColor.color otherwise use
+ * self.color for the rest of the graph
+ */
+@property(strong) NSArray<PNLineChartColorRange *> *rangeColors;
+
+/**
+ * If PNLineChartPointStyle is circle, this returns the circle's diameter.
+ * If PNLineChartPointStyle is square, each point is a square with each side equal in length to this value.
+ */
+@property (nonatomic, assign) CGFloat inflexionPointWidth;
+
+@property (nonatomic, assign) CGFloat lineWidth;
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChartData.m b/PNChartdemo/PNChart/PNLineChartData.m
new file mode 100755
index 0000000..bbf2647
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChartData.m
@@ -0,0 +1,54 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import "PNLineChartData.h"
+
+
+@implementation PNLineChartColorRange
+
+- (id)initWithRange:(NSRange)range color:(UIColor *)color {
+    self = [super init];
+    if (self) {
+        self.range = range;
+        self.color = color;
+    }
+    return self;
+}
+
+
+- (id)copyWithZone:(NSZone *)zone {
+    PNLineChartColorRange *copy = [[self class] allocWithZone:zone];
+    copy.color = self.color;
+    copy.range = self.range;
+    return copy;
+}
+
+@end
+
+@implementation PNLineChartData
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        [self setupDefaultValues];
+    }
+    
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    _inflexionPointStyle = PNLineChartPointStyleNone;
+    _inflexionPointWidth = 6.f;
+    _lineWidth = 2.f;
+    _alpha = 1.f;
+    _showPointLabel = NO;
+    _pointLabelColor = [UIColor blackColor];
+    _pointLabelFormat = @"%1.f";
+    _rangeColors = nil;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChartDataItem.h b/PNChartdemo/PNChart/PNLineChartDataItem.h
new file mode 100755
index 0000000..ad2d23d
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChartDataItem.h
@@ -0,0 +1,17 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNLineChartDataItem : NSObject
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y;
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY;
+
+@property (readonly) CGFloat y; // should be within the y range
+@property (readonly) CGFloat rawY; // this is the raw value, used for point label.
+
+@end
diff --git a/PNChartdemo/PNChart/PNLineChartDataItem.m b/PNChartdemo/PNChart/PNLineChartDataItem.m
new file mode 100755
index 0000000..1beea91
--- /dev/null
+++ b/PNChartdemo/PNChart/PNLineChartDataItem.m
@@ -0,0 +1,38 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import "PNLineChartDataItem.h"
+
+@interface PNLineChartDataItem ()
+
+- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY;
+
+@property (readwrite) CGFloat y;    // should be within the y range
+@property (readwrite) CGFloat rawY; // this is the raw value, used for point label.
+
+@end
+
+@implementation PNLineChartDataItem
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y
+{
+    return [[PNLineChartDataItem alloc] initWithY:y andRawY:y];
+}
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY {
+    return [[PNLineChartDataItem alloc] initWithY:y andRawY:rawY];
+}
+
+- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY
+{
+    if ((self = [super init])) {
+        self.y = y;
+        self.rawY = rawY;
+    }
+
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNPieChart.h b/PNChartdemo/PNChart/PNPieChart.h
new file mode 100755
index 0000000..204afb5
--- /dev/null
+++ b/PNChartdemo/PNChart/PNPieChart.h
@@ -0,0 +1,68 @@
+//
+//  PNPieChart.h
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNPieChartDataItem.h"
+#import "PNGenericChart.h"
+#import "PNChartDelegate.h"
+
+@interface PNPieChart : PNGenericChart
+
+- (id)initWithFrame:(CGRect)frame items:(NSArray *)items;
+
+@property (nonatomic, readonly) NSArray	*items;
+
+/** Default is 18-point Avenir Medium. */
+@property (nonatomic) UIFont  *descriptionTextFont;
+
+/** Default is white. */
+@property (nonatomic) UIColor *descriptionTextColor;
+
+/** Default is black, with an alpha of 0.4. */
+@property (nonatomic) UIColor *descriptionTextShadowColor;
+
+/** Default is CGSizeMake(0, 1). */
+@property (nonatomic) CGSize   descriptionTextShadowOffset;
+
+/** Default is 1.0. */
+@property (nonatomic) NSTimeInterval duration;
+
+/** Show only values, this is useful when legend is present */
+@property (nonatomic) BOOL showOnlyValues;
+
+/** Show absolute values not relative i.e. percentages */
+@property (nonatomic) BOOL showAbsoluteValues;
+
+/** Hide percentage labels less than cutoff value */
+@property (nonatomic, assign) CGFloat labelPercentageCutoff;
+
+/** Default YES. */
+@property (nonatomic) BOOL shouldHighlightSectorOnTouch;
+
+/** Current outer radius. Override recompute() to change this. **/
+@property (nonatomic) CGFloat outerCircleRadius;
+
+/** Current inner radius. Override recompute() to change this. **/
+@property (nonatomic) CGFloat innerCircleRadius;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+/** Update chart items. Does not update chart itself. */
+- (void)updateChartData:(NSArray *)data;
+
+/** Multiple selection */
+@property (nonatomic, assign) BOOL enableMultipleSelection;
+
+/** show only tiles, not values or percentage */
+@property (nonatomic) BOOL hideValues;
+
+- (void)strokeChart;
+
+- (void)recompute;
+
+@end
diff --git a/PNChartdemo/PNChart/PNPieChart.m b/PNChartdemo/PNChart/PNPieChart.m
new file mode 100755
index 0000000..ae9ab7a
--- /dev/null
+++ b/PNChartdemo/PNChart/PNPieChart.m
@@ -0,0 +1,508 @@
+//
+//  PNPieChart.m
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import "PNPieChart.h"
+//needed for the expected label size
+#import "PNLineChart.h"
+
+@interface PNPieChart()
+
+@property (nonatomic) NSArray *items;
+@property (nonatomic) NSArray *endPercentages;
+
+@property (nonatomic) UIView         *contentView;
+@property (nonatomic) CAShapeLayer   *pieLayer;
+@property (nonatomic) NSMutableArray *descriptionLabels;
+@property (strong, nonatomic) CAShapeLayer *sectorHighlight;
+
+@property (nonatomic, strong) NSMutableDictionary *selectedItems;
+
+- (void)loadDefault;
+
+- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index;
+- (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index;
+- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index;
+- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index;
+- (CGFloat)ratioForItemAtIndex:(NSUInteger)index;
+
+- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
+                               borderWidth:(CGFloat)borderWidth
+                                 fillColor:(UIColor *)fillColor
+                               borderColor:(UIColor *)borderColor
+                           startPercentage:(CGFloat)startPercentage
+                             endPercentage:(CGFloat)endPercentage;
+
+
+@end
+
+
+@implementation PNPieChart
+
+-(id)initWithFrame:(CGRect)frame items:(NSArray *)items{
+    self = [self initWithFrame:frame];
+    if(self){
+        _items = [NSArray arrayWithArray:items];
+        [self baseInit];
+    }
+    
+    return self;
+}
+
+- (void)awakeFromNib{
+    [super awakeFromNib];
+    [self baseInit];
+}
+
+- (void)baseInit{
+    _selectedItems = [NSMutableDictionary dictionary];
+    //������������������,���������������������������������������������,������������������,���������������,���������������view���������,���������������������������������
+    
+    CGFloat minimal = (CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds)) ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds);
+    
+    _outerCircleRadius  = minimal / 2;
+    _innerCircleRadius  = minimal / 6;
+//    _outerCircleRadius  = CGRectGetWidth(self.bounds) / 2;
+//    _innerCircleRadius  = CGRectGetWidth(self.bounds) / 6;
+    _descriptionTextColor = [UIColor whiteColor];
+    _descriptionTextFont  = [UIFont fontWithName:@"Avenir-Medium" size:18.0];
+    _descriptionTextShadowColor  = [[UIColor blackColor] colorWithAlphaComponent:0.4];
+    _descriptionTextShadowOffset =  CGSizeMake(0, 1);
+    _duration = 1.0;
+    _shouldHighlightSectorOnTouch = YES;
+    _enableMultipleSelection = NO;
+    _hideValues = NO;
+    
+    [super setupDefaultValues];
+    [self loadDefault];
+}
+
+- (void)loadDefault{
+    __block CGFloat currentTotal = 0;
+    CGFloat total = [[self.items valueForKeyPath:@"@sum.value"] floatValue];
+    NSMutableArray *endPercentages = [NSMutableArray new];
+    [_items enumerateObjectsUsingBlock:^(PNPieChartDataItem *item, NSUInteger idx, BOOL *stop) {
+        if (total == 0){
+            [endPercentages addObject:@(1.0 / _items.count * (idx + 1))];
+        }else{
+            currentTotal += item.value;
+            [endPercentages addObject:@(currentTotal / total)];
+        }
+    }];
+    self.endPercentages = [endPercentages copy];
+    
+    [_contentView removeFromSuperview];
+    _contentView = [[UIView alloc] initWithFrame:self.bounds];
+    [self addSubview:_contentView];
+    _descriptionLabels = [NSMutableArray new];
+    
+    _pieLayer = [CAShapeLayer layer];
+    [_contentView.layer addSublayer:_pieLayer];
+
+}
+
+/** Override this to change how inner attributes are computed. **/
+- (void)recompute {
+    
+    //������
+    CGFloat minimal = (CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds)) ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds);
+    self.outerCircleRadius = minimal / 2;
+    self.innerCircleRadius = minimal / 6;
+}
+
+#pragma mark -
+
+- (void)strokeChart{
+    [self loadDefault];
+    [self recompute];
+    
+    PNPieChartDataItem *currentItem;
+    for (int i = 0; i < _items.count; i++) {
+        currentItem = [self dataItemForIndex:i];
+        
+        
+        CGFloat startPercentage = [self startPercentageForItemAtIndex:i];
+        CGFloat endPercentage   = [self endPercentageForItemAtIndex:i];
+        
+        CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+        CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
+        
+        CAShapeLayer *currentPieLayer =	[self newCircleLayerWithRadius:radius
+                                                           borderWidth:borderWidth
+                                                             fillColor:[UIColor clearColor]
+                                                           borderColor:currentItem.color
+                                                       startPercentage:startPercentage
+                                                         endPercentage:endPercentage];
+        [_pieLayer addSublayer:currentPieLayer];
+    }
+    
+    [self maskChart];
+    
+    for (int i = 0; i < _items.count; i++) {
+        UILabel *descriptionLabel =  [self descriptionLabelForItemAtIndex:i];
+        [_contentView addSubview:descriptionLabel];
+        [_descriptionLabels addObject:descriptionLabel];
+    }
+    
+    [self addAnimationIfNeeded];
+}
+
+- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index{
+    PNPieChartDataItem *currentDataItem = [self dataItemForIndex:index];
+    CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+    CGFloat centerPercentage = ([self startPercentageForItemAtIndex:index] + [self endPercentageForItemAtIndex:index])/ 2;
+    CGFloat rad = centerPercentage * 2 * M_PI;
+    
+    UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
+    NSString *titleText = currentDataItem.textDescription;
+    
+    NSString *titleValue;
+    
+    if (self.showAbsoluteValues) {
+        titleValue = [NSString stringWithFormat:@"%.0f",currentDataItem.value];
+    }else{
+        titleValue = [NSString stringWithFormat:@"%.0f%%",[self ratioForItemAtIndex:index] * 100];
+    }
+    
+    if (self.hideValues)
+        descriptionLabel.text = titleText;
+    else if(!titleText || self.showOnlyValues)
+        descriptionLabel.text = titleValue;
+    else {
+        NSString* str = [titleValue stringByAppendingString:[NSString stringWithFormat:@"\n%@",titleText]];
+        descriptionLabel.text = str ;
+    }
+    
+    //If value is less than cutoff, show no label
+    if ([self ratioForItemAtIndex:index] < self.labelPercentageCutoff )
+    {
+        descriptionLabel.text = nil;
+    }
+    
+    CGPoint center = CGPointMake(_outerCircleRadius + distance * sin(rad),
+                                 _outerCircleRadius - distance * cos(rad));
+    
+    descriptionLabel.font = _descriptionTextFont;
+    CGSize labelSize = [descriptionLabel.text sizeWithAttributes:@{NSFontAttributeName:descriptionLabel.font}];
+    descriptionLabel.frame = CGRectMake(descriptionLabel.frame.origin.x, descriptionLabel.frame.origin.y,
+                                        descriptionLabel.frame.size.width, labelSize.height);
+    descriptionLabel.numberOfLines   = 0;
+    descriptionLabel.textColor       = _descriptionTextColor;
+    descriptionLabel.shadowColor     = _descriptionTextShadowColor;
+    descriptionLabel.shadowOffset    = _descriptionTextShadowOffset;
+    descriptionLabel.textAlignment   = NSTextAlignmentCenter;
+    descriptionLabel.center          = center;
+    descriptionLabel.alpha           = 0;
+    descriptionLabel.backgroundColor = [UIColor clearColor];
+    return descriptionLabel;
+}
+
+- (void)updateChartData:(NSArray *)items {
+    self.items = items;
+}
+
+- (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index{
+    return self.items[index];
+}
+
+- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index{
+    if(index == 0){
+        return 0;
+    }
+    
+    return [_endPercentages[index - 1] floatValue];
+}
+
+- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index{
+    return [_endPercentages[index] floatValue];
+}
+
+- (CGFloat)ratioForItemAtIndex:(NSUInteger)index{
+    return [self endPercentageForItemAtIndex:index] - [self startPercentageForItemAtIndex:index];
+}
+
+#pragma mark private methods
+
+- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
+                               borderWidth:(CGFloat)borderWidth
+                                 fillColor:(UIColor *)fillColor
+                               borderColor:(UIColor *)borderColor
+                           startPercentage:(CGFloat)startPercentage
+                             endPercentage:(CGFloat)endPercentage{
+    CAShapeLayer *circle = [CAShapeLayer layer];
+    
+    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds),CGRectGetMidY(self.bounds));
+    
+    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
+                                                        radius:radius
+                                                    startAngle:-M_PI_2
+                                                      endAngle:M_PI_2 * 3
+                                                     clockwise:YES];
+    
+    circle.fillColor   = fillColor.CGColor;
+    circle.strokeColor = borderColor.CGColor;
+    circle.strokeStart = startPercentage;
+    circle.strokeEnd   = endPercentage;
+    circle.lineWidth   = borderWidth;
+    circle.path        = path.CGPath;
+    
+    return circle;
+}
+
+- (void)maskChart{
+    CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+    CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
+    CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:radius
+                                                 borderWidth:borderWidth
+                                                   fillColor:[UIColor clearColor]
+                                                 borderColor:[UIColor blackColor]
+                                             startPercentage:0
+                                               endPercentage:1];
+    
+    _pieLayer.mask = maskLayer;
+}
+
+- (void)addAnimationIfNeeded{
+    if (self.displayAnimated) {
+        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        animation.duration  = _duration;
+        animation.fromValue = @0;
+        animation.toValue   = @1;
+        animation.delegate  = self;
+        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        animation.removedOnCompletion = YES;
+        [_pieLayer.mask addAnimation:animation forKey:@"circleAnimation"];
+    }
+    else {
+        // Add description labels since no animation is required
+        [_descriptionLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+            [obj setAlpha:1];
+        }];
+    }
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
+    [_descriptionLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        [UIView animateWithDuration:0.2 animations:^(){
+            [obj setAlpha:1];
+        }];
+    }];
+}
+
+- (void)didTouchAt:(CGPoint)touchLocation
+{
+    CGPoint circleCenter = CGPointMake(_contentView.bounds.size.width/2, _contentView.bounds.size.height/2);
+    
+    CGFloat distanceFromCenter = sqrtf(powf((touchLocation.y - circleCenter.y),2) + powf((touchLocation.x - circleCenter.x),2));
+    
+    if (distanceFromCenter < _innerCircleRadius) {
+        if ([self.delegate respondsToSelector:@selector(didUnselectPieItem)]) {
+            [self.delegate didUnselectPieItem];
+        }
+        [self.sectorHighlight removeFromSuperlayer];
+        return;
+    }
+    
+    CGFloat percentage = [self findPercentageOfAngleInCircle:circleCenter fromPoint:touchLocation];
+    int index = 0;
+    while (percentage > [self endPercentageForItemAtIndex:index]) {
+        index ++;
+    }
+    
+    if ([self.delegate respondsToSelector:@selector(userClickedOnPieIndexItem:)]) {
+        [self.delegate userClickedOnPieIndexItem:index];
+    }
+    
+    if (self.shouldHighlightSectorOnTouch)
+    {
+        if (!self.enableMultipleSelection)
+        {
+            if (self.sectorHighlight)
+                [self.sectorHighlight removeFromSuperlayer];
+        }
+        
+        PNPieChartDataItem *currentItem = [self dataItemForIndex:index];
+        
+        CGFloat red,green,blue,alpha;
+        UIColor *old = currentItem.color;
+        [old getRed:&red green:&green blue:&blue alpha:&alpha];
+        alpha /= 2;
+        UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
+        
+        CGFloat startPercentage = [self startPercentageForItemAtIndex:index];
+        CGFloat endPercentage   = [self endPercentageForItemAtIndex:index];
+        
+        self.sectorHighlight = [self newCircleLayerWithRadius:_outerCircleRadius + 5
+                                                  borderWidth:10
+                                                    fillColor:[UIColor clearColor]
+                                                  borderColor:newColor
+                                              startPercentage:startPercentage
+                                                endPercentage:endPercentage];
+        
+        if (self.enableMultipleSelection)
+        {
+            NSString *dictIndex = [NSString stringWithFormat:@"%d", index];
+            CAShapeLayer *indexShape = [self.selectedItems valueForKey:dictIndex];
+            if (indexShape)
+            {
+                [indexShape removeFromSuperlayer];
+                [self.selectedItems removeObjectForKey:dictIndex];
+            }
+            else
+            {
+                [self.selectedItems setObject:self.sectorHighlight forKey:dictIndex];
+                [_contentView.layer addSublayer:self.sectorHighlight];
+            }
+        }
+        else
+        {
+            [_contentView.layer addSublayer:self.sectorHighlight];
+        }
+    }
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:_contentView];
+        [self didTouchAt:touchLocation];
+    }
+}
+
+- (CGFloat) findPercentageOfAngleInCircle:(CGPoint)center fromPoint:(CGPoint)reference{
+    //Find angle of line Passing In Reference And Center
+    CGFloat angleOfLine = atanf((reference.y - center.y) / (reference.x - center.x));
+    CGFloat percentage = (angleOfLine + M_PI/2)/(2 * M_PI);
+    return (reference.x - center.x) > 0 ? percentage : percentage + .5;
+}
+
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{
+    if ([self.items count] < 1) {
+        return nil;
+    }
+    
+    /* This is a small circle that refers to the chart data */
+    CGFloat legendCircle = 16;
+    
+    CGFloat hSpacing = 0;
+    
+    CGFloat beforeLabel = legendCircle + hSpacing;
+    
+    /* x and y are the coordinates of the starting point of each legend item */
+    CGFloat x = 0;
+    CGFloat y = 0;
+    
+    /* accumulated width and height */
+    CGFloat totalWidth = 0;
+    CGFloat totalHeight = 0;
+    
+    NSMutableArray *legendViews = [[NSMutableArray alloc] init];
+    
+    /* Determine the max width of each legend item */
+    CGFloat maxLabelWidth;
+    if (self.legendStyle == PNLegendItemStyleStacked) {
+        maxLabelWidth = mWidth - beforeLabel;
+    }else{
+        maxLabelWidth = MAXFLOAT;
+    }
+    
+    /* this is used when labels wrap text and the line
+     * should be in the middle of the first row */
+    CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test"
+                                              withWidth:MAXFLOAT
+                                                   font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height;
+    
+    NSUInteger counter = 0;
+    NSUInteger rowWidth = 0;
+    NSUInteger rowMaxHeight = 0;
+    
+    for (PNPieChartDataItem *pdata in self.items) {
+        /* Expected label size*/
+        CGSize labelsize = [PNLineChart sizeOfString:pdata.textDescription
+                                           withWidth:maxLabelWidth
+                                                font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]];
+        
+        if ((rowWidth + labelsize.width + beforeLabel > mWidth)&&(self.legendStyle == PNLegendItemStyleSerial)) {
+            rowWidth = 0;
+            x = 0;
+            y += rowMaxHeight;
+            rowMaxHeight = 0;
+        }
+        rowWidth += labelsize.width + beforeLabel;
+        totalWidth = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(rowWidth, totalWidth) : fmaxf(totalWidth, labelsize.width + beforeLabel);
+        // Add inflexion type
+        [legendViews addObject:[self drawInflexion:legendCircle * .6
+                                            center:CGPointMake(x + legendCircle / 2, y + singleRowHeight / 2)
+                                          andColor:pdata.color]];
+        
+        
+        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + beforeLabel, y, labelsize.width, labelsize.height)];
+        label.text = pdata.textDescription;
+        label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor];
+        label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f];
+        label.lineBreakMode = NSLineBreakByWordWrapping;
+        label.numberOfLines = 0;
+        
+        
+        rowMaxHeight = fmaxf(rowMaxHeight, labelsize.height);
+        x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + beforeLabel;
+        y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0;
+        
+        
+        totalHeight = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height;
+        [legendViews addObject:label];
+        counter ++;
+    }
+    
+    UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, totalWidth, totalHeight)];
+    
+    for (UIView* v in legendViews) {
+        [legend addSubview:v];
+    }
+    return legend;
+}
+
+
+- (UIImageView*)drawInflexion:(CGFloat)size center:(CGPoint)center andColor:(UIColor*)color
+{
+    //Make the size a little bigger so it includes also border stroke
+    CGSize aSize = CGSizeMake(size, size);
+    
+    
+    UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    CGContextAddArc(context, size/2, size/ 2, size/2, 0, M_PI*2, YES);
+    
+    
+    //Set some fill color
+    CGContextSetFillColorWithColor(context, color.CGColor);
+    
+    //Finally draw
+    CGContextDrawPath(context, kCGPathFill);
+    
+    //now get the image from the context
+    UIImage *squareImage = UIGraphicsGetImageFromCurrentImageContext();
+    
+    UIGraphicsEndImageContext();
+    
+    //// Translate origin
+    CGFloat originX = center.x - (size) / 2.0;
+    CGFloat originY = center.y - (size) / 2.0;
+    
+    UIImageView *squareImageView = [[UIImageView alloc]initWithImage:squareImage];
+    [squareImageView setFrame:CGRectMake(originX, originY, size, size)];
+    return squareImageView;
+}
+
+/* Redraw the chart on autolayout */
+-(void)layoutSubviews {
+    [super layoutSubviews];
+    [self strokeChart];
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNPieChartDataItem.h b/PNChartdemo/PNChart/PNPieChartDataItem.h
new file mode 100755
index 0000000..08d48e9
--- /dev/null
+++ b/PNChartdemo/PNChart/PNPieChartDataItem.h
@@ -0,0 +1,25 @@
+//
+//  PNPieChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNPieChartDataItem : NSObject
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color;
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color
+                      description:(NSString *)description;
+
+@property (nonatomic) CGFloat   value;
+@property (nonatomic) UIColor  *color;
+@property (nonatomic) NSString *textDescription;
+
+@end
diff --git a/PNChartdemo/PNChart/PNPieChartDataItem.m b/PNChartdemo/PNChart/PNPieChartDataItem.m
new file mode 100755
index 0000000..4bda818
--- /dev/null
+++ b/PNChartdemo/PNChart/PNPieChartDataItem.m
@@ -0,0 +1,38 @@
+//
+//  PNPieChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import "PNPieChartDataItem.h"
+#import <UIKit/UIKit.h>
+
+@implementation PNPieChartDataItem
+
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color{
+	PNPieChartDataItem *item = [PNPieChartDataItem new];
+	item.value = value;
+	item.color  = color;
+	return item;
+}
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color
+                      description:(NSString *)description {
+	PNPieChartDataItem *item = [PNPieChartDataItem dataItemWithValue:value color:color];
+	item.textDescription = description;
+	return item;
+}
+
+- (void)setValue:(CGFloat)value{
+    NSAssert(value >= 0, @"value should >= 0");
+    if (value != _value){
+        _value = value;
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNRadarChart.h b/PNChartdemo/PNChart/PNRadarChart.h
new file mode 100755
index 0000000..87871d0
--- /dev/null
+++ b/PNChartdemo/PNChart/PNRadarChart.h
@@ -0,0 +1,52 @@
+//
+//  PNRadarChart.h
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNGenericChart.h"
+#import "PNRadarChartDataItem.h"
+
+#define MAXCIRCLE 20
+
+typedef NS_ENUM(NSUInteger, PNRadarChartLabelStyle) {
+    PNRadarChartLabelStyleCircle = 0,
+    PNRadarChartLabelStyleHorizontal,
+    PNRadarChartLabelStyleHidden,
+};
+
+@interface PNRadarChart : PNGenericChart
+
+-(id)initWithFrame:(CGRect)frame  items:(NSArray *)items valueDivider:(CGFloat)unitValue;
+/** 
+ *Draws the chart in an animated fashion.
+ */
+-(void)strokeChart;
+
+/** Array of `RadarChartDataItem` objects, one for each corner. */
+@property (nonatomic) NSArray *chartData;
+/** The unit of this chart ,default is 1 */
+@property (nonatomic) CGFloat valueDivider;
+/** The maximum for the range of values to display on the chart */
+@property (nonatomic) CGFloat maxValue;
+/** Default is gray. */
+@property (nonatomic) UIColor *webColor;
+/** Default is green , with an alpha of 0.7 */
+@property (nonatomic) UIColor *plotColor;
+/** Default is black */
+@property (nonatomic) UIColor *fontColor;
+/** Default is orange */
+@property (nonatomic) UIColor *graduationColor;
+/** Default is 15 */
+@property (nonatomic) CGFloat fontSize;
+/** Controls the labels display style that around chart */
+@property (nonatomic, assign) PNRadarChartLabelStyle labelStyle;
+/** Tap the label will display detail value ,default is YES. */
+@property (nonatomic, assign) BOOL isLabelTouchable;
+/** is show graduation on the chart ,default is NO. */
+@property (nonatomic, assign) BOOL isShowGraduation;
+
+@end
diff --git a/PNChartdemo/PNChart/PNRadarChart.m b/PNChartdemo/PNChart/PNRadarChart.m
new file mode 100755
index 0000000..9dace2b
--- /dev/null
+++ b/PNChartdemo/PNChart/PNRadarChart.m
@@ -0,0 +1,373 @@
+//
+//  PNRadarChart.m
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import "PNRadarChart.h"
+
+@interface PNRadarChart()
+
+@property (nonatomic) CGFloat centerX;
+@property (nonatomic) CGFloat centerY;
+@property (nonatomic) NSMutableArray *pointsToWebArrayArray;
+@property (nonatomic) NSMutableArray *pointsToPlotArray;
+@property (nonatomic) UILabel *detailLabel;
+@property (nonatomic) CGFloat lengthUnit;
+@property (nonatomic) CAShapeLayer *chartPlot;
+
+@end
+
+
+@implementation PNRadarChart
+
+- (id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue {
+    self=[super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = [UIColor clearColor];
+        self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+
+        //Public iVar
+        if ([items count]< 3)//At least three corners of A polygon ,If the count of items is less than 3 will add 3 default values
+        {
+            NSLog( @"At least three items!");
+            NSArray *defaultArray = @[[PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      ];
+           defaultArray = [defaultArray arrayByAddingObjectsFromArray:items];
+            _chartData = [NSArray arrayWithArray:defaultArray];
+        }else{
+            _chartData = [NSArray arrayWithArray:items];
+        }
+        _valueDivider = unitValue;
+        _maxValue = 1;
+        _webColor = [UIColor grayColor];
+        _plotColor = [UIColor colorWithRed:.4 green:.8 blue:.4 alpha:.7];
+        _fontColor = [UIColor blackColor];
+        _graduationColor = [UIColor orangeColor];
+        _fontSize = 15;
+        _labelStyle = PNRadarChartLabelStyleHorizontal;
+        _isLabelTouchable = YES;
+        _isShowGraduation = NO;
+        
+        //Private iVar
+        _centerX = frame.size.width/2;
+        _centerY = frame.size.height/2;
+        _pointsToWebArrayArray = [NSMutableArray array];
+        _pointsToPlotArray = [NSMutableArray array];
+        _lengthUnit = 0;
+        _chartPlot = [CAShapeLayer layer];
+        _chartPlot.lineCap = kCALineCapButt;
+        _chartPlot.lineWidth = 1.0;
+        [self.layer addSublayer:_chartPlot];
+        
+        [super setupDefaultValues];
+         //init detailLabel
+        _detailLabel = [[UILabel alloc] init];
+        _detailLabel.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.1 alpha:.9];
+        _detailLabel.textAlignment = NSTextAlignmentCenter;
+        _detailLabel.textColor = [UIColor colorWithWhite:1 alpha:1];
+        _detailLabel.font = [UIFont systemFontOfSize:15];
+        [_detailLabel setHidden:YES];
+        [self addSubview:_detailLabel];
+        
+        [self strokeChart];
+    }
+    return self;
+}
+
+#pragma mark - main
+- (void)calculateChartPoints {
+    [_pointsToPlotArray removeAllObjects];
+    [_pointsToWebArrayArray removeAllObjects];
+    
+    //init Descriptions , Values and Angles.
+    NSMutableArray *descriptions = [NSMutableArray array];
+    NSMutableArray *values = [NSMutableArray array];
+    NSMutableArray *angles = [NSMutableArray array];
+    for (int i=0;i<_chartData.count;i++) {
+        PNRadarChartDataItem *item = (PNRadarChartDataItem *)[_chartData objectAtIndex:i];
+        [descriptions addObject:item.textDescription];
+        [values addObject:[NSNumber numberWithFloat:item.value]];
+        CGFloat angleValue = (float)i/(float)[_chartData count]*2*M_PI;
+        [angles addObject:[NSNumber numberWithFloat:angleValue]];
+    }
+    
+    //calculate all the lengths
+    _maxValue = [self getMaxValueFromArray:values];
+    CGFloat margin = 0;
+    if (_labelStyle==PNRadarChartLabelStyleCircle) {
+        margin = MIN(_centerX , _centerY)*3/10;
+    }else if (_labelStyle==PNRadarChartLabelStyleHorizontal) {
+        margin = [self getMaxWidthLabelFromArray:descriptions withFontSize:_fontSize];
+    }
+    CGFloat maxLength = ceil(MIN(_centerX, _centerY) - margin);
+    int plotCircles = (_maxValue/_valueDivider);
+    if (plotCircles > MAXCIRCLE) {
+        NSLog(@"Circle number is higher than max");
+        plotCircles = MAXCIRCLE;
+        _valueDivider = _maxValue/plotCircles;
+    }
+    _lengthUnit = maxLength/plotCircles;
+    NSArray *lengthArray = [self getLengthArrayWithCircleNum:(int)plotCircles];
+
+    //get all the points and plot
+    for (NSNumber *lengthNumber in lengthArray) {
+        CGFloat length = [lengthNumber floatValue];
+        [_pointsToWebArrayArray addObject:[self getWebPointWithLength:length angleArray:angles]];
+    }
+    int section = 0;
+    for (id value in values) {
+        CGFloat valueFloat = [value floatValue];
+        if (valueFloat>_maxValue) {
+            NSString *reason = [NSString stringWithFormat:@"Value number is higher than max -value: %f - maxValue: %f",valueFloat,_maxValue];
+            @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
+            return;
+        }
+        
+        CGFloat length = valueFloat/_maxValue*maxLength;
+        CGFloat angle = [[angles objectAtIndex:section] floatValue];
+        CGFloat x = _centerX +length*cos(angle);
+        CGFloat y = _centerY +length*sin(angle);
+        NSValue* point = [NSValue valueWithCGPoint:CGPointMake(x, y)];
+        [_pointsToPlotArray addObject:point];
+        section++;
+    }
+    //set the labels
+    [self drawLabelWithMaxLength:maxLength labelArray:descriptions angleArray:angles];
+    
+ }
+#pragma mark - Draw
+
+- (void)drawRect:(CGRect)rect {
+    // Drawing backgound
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextClearRect(context, rect);
+    int section = 0;
+    //circles
+    for(NSArray *pointArray in _pointsToWebArrayArray){
+        //plot backgound
+        CGContextRef graphContext = UIGraphicsGetCurrentContext();
+        CGContextBeginPath(graphContext);
+        CGPoint beginPoint = [[pointArray objectAtIndex:0] CGPointValue];
+        CGContextMoveToPoint(graphContext, beginPoint.x, beginPoint.y);
+        for(NSValue* pointValue in pointArray){
+            CGPoint point = [pointValue CGPointValue];
+            CGContextAddLineToPoint(graphContext, point.x, point.y);
+        }
+        CGContextAddLineToPoint(graphContext, beginPoint.x, beginPoint.y);
+        CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
+        CGContextStrokePath(graphContext);
+        
+    }
+    //cuts
+    NSArray *largestPointArray = [_pointsToWebArrayArray lastObject];
+    for (NSValue *pointValue in largestPointArray){
+        section++;
+        if (section==1&&_isShowGraduation)continue;
+        
+        CGContextRef graphContext = UIGraphicsGetCurrentContext();
+        CGContextBeginPath(graphContext);
+        CGContextMoveToPoint(graphContext, _centerX, _centerY);
+        CGPoint point = [pointValue CGPointValue];
+        CGContextAddLineToPoint(graphContext, point.x, point.y);
+        CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
+        CGContextStrokePath(graphContext);
+    }
+    
+    
+}
+
+- (void)strokeChart {
+    
+    [self calculateChartPoints];
+    [self setNeedsDisplay];
+    [_detailLabel setHidden:YES];
+    
+    //Draw plot
+    [_chartPlot removeAllAnimations];
+    UIBezierPath *plotline = [UIBezierPath bezierPath];
+    CGPoint beginPoint = [[_pointsToPlotArray objectAtIndex:0] CGPointValue];
+    [plotline moveToPoint:CGPointMake(beginPoint.x, beginPoint.y)];
+    for(NSValue *pointValue in _pointsToPlotArray){
+        CGPoint point = [pointValue CGPointValue];
+        [plotline addLineToPoint:CGPointMake(point.x ,point.y)];
+        
+    }
+    [plotline setLineWidth:1];
+    [plotline setLineCapStyle:kCGLineCapButt];
+    
+    _chartPlot.path = plotline.CGPath;
+    
+    _chartPlot.fillColor = _plotColor.CGColor;
+
+    [self addAnimationIfNeeded];
+    [self showGraduation];
+}
+
+#pragma mark - Helper
+
+- (void)drawLabelWithMaxLength:(CGFloat)maxLength labelArray:(NSArray *)labelArray angleArray:(NSArray *)angleArray {
+    //set labels
+    int labelTag = 121;
+    while (true) {
+        UIView *label = [self viewWithTag:labelTag];
+        if(!label)break;
+        [label removeFromSuperview];
+    }
+    int section = 0;
+    CGFloat labelLength = maxLength + maxLength/10;
+    
+    for (NSString *labelString in labelArray) {
+        CGFloat angle = [[angleArray objectAtIndex:section] floatValue];
+        CGFloat x = _centerX + labelLength *cos(angle);
+        CGFloat y = _centerY + labelLength *sin(angle);
+        
+        UILabel *label = [[UILabel alloc] init] ;
+        label.backgroundColor = [UIColor clearColor];
+        label.font = [UIFont systemFontOfSize:_fontSize];
+        label.text = labelString;
+        label.tag = labelTag;
+        CGSize detailSize = [labelString sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
+        
+        switch (_labelStyle) {
+            case PNRadarChartLabelStyleCircle:
+                label.frame = CGRectMake(x-5*_fontSize/2, y-_fontSize/2, 5*_fontSize, _fontSize);
+                label.transform = CGAffineTransformMakeRotation(((float)section/[labelArray count])*(2*M_PI)+M_PI_2);
+                label.textAlignment = NSTextAlignmentCenter;
+                
+                break;
+            case PNRadarChartLabelStyleHorizontal:
+                if (x<_centerX) {
+                    label.frame = CGRectMake(x-detailSize.width, y-detailSize.height/2, detailSize.width, detailSize.height);
+                    label.textAlignment = NSTextAlignmentRight;
+                }else{
+                    label.frame = CGRectMake(x, y-detailSize.height/2, detailSize.width , detailSize.height);
+                    label.textAlignment = NSTextAlignmentLeft;
+                }
+                break;
+            case PNRadarChartLabelStyleHidden:
+                [label setHidden:YES];
+                break;
+            default:
+                break;
+        }
+        [label sizeToFit];
+        
+        label.userInteractionEnabled = YES;
+        UITapGestureRecognizer *tapLabelGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapLabel:)];
+        [label addGestureRecognizer:tapLabelGesture];
+        [self addSubview:label];
+        
+        section ++;
+    }
+    
+}
+
+- (void)tapLabel:(UITapGestureRecognizer *)recognizer {
+    UILabel *label=(UILabel*)recognizer.view;
+    _detailLabel.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y-30, 50, 25);
+    for (PNRadarChartDataItem *item in _chartData) {
+        if ([label.text isEqualToString:item.textDescription]) {
+            _detailLabel.text =  [NSString stringWithFormat:@"%.2f", item.value];
+            break;
+        }
+    }
+    [_detailLabel setHidden:NO];
+    
+}
+
+- (void)showGraduation {
+    int labelTag = 112;
+    while (true) {
+        UIView *label = [self viewWithTag:labelTag];
+        if(!label)break;
+        [label removeFromSuperview];
+    }
+    int section = 0;
+    for (NSArray *pointsArray in _pointsToWebArrayArray) {
+        section++;
+        CGPoint labelPoint = [[pointsArray objectAtIndex:0] CGPointValue];
+        UILabel *graduationLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelPoint.x-_lengthUnit, labelPoint.y-_lengthUnit*5/8, _lengthUnit*5/8, _lengthUnit)];
+        graduationLabel.adjustsFontSizeToFitWidth = YES;
+        graduationLabel.tag = labelTag;
+        graduationLabel.font = [UIFont systemFontOfSize:ceil(_lengthUnit)];
+        graduationLabel.textColor = [UIColor orangeColor];
+        graduationLabel.text = [NSString stringWithFormat:@"%.0f",_valueDivider*section];
+        [self addSubview:graduationLabel];
+        if (_isShowGraduation) {
+            [graduationLabel setHidden:NO];
+        }else{
+            [graduationLabel setHidden:YES];}
+    }
+
+}
+
+- (NSArray *)getWebPointWithLength:(CGFloat)length angleArray:(NSArray *)angleArray {
+    NSMutableArray *pointArray = [NSMutableArray array];
+    for (NSNumber *angleNumber in angleArray) {
+        CGFloat angle = [angleNumber floatValue];
+        CGFloat x = _centerX + length*cos(angle);
+        CGFloat y = _centerY + length*sin(angle);
+        [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(x,y)]];
+    }
+    return pointArray;
+    
+}
+
+- (NSArray *)getLengthArrayWithCircleNum:(int)plotCircles {
+    NSMutableArray *lengthArray = [NSMutableArray array];
+    CGFloat length = 0;
+    for (int i = 0; i < plotCircles; i++) {
+        length += _lengthUnit;
+        [lengthArray addObject:[NSNumber numberWithFloat:length]];
+    }
+    return lengthArray;
+}
+
+- (CGFloat)getMaxWidthLabelFromArray:(NSArray *)keyArray withFontSize:(CGFloat)size {
+    CGFloat maxWidth = 0;
+    for (NSString *str in keyArray) {
+        CGSize detailSize = [str sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
+        maxWidth = MAX(maxWidth, detailSize.width);
+    }
+    return maxWidth;
+}
+
+- (CGFloat)getMaxValueFromArray:(NSArray *)valueArray {
+    CGFloat max = _maxValue;
+    for (NSNumber *valueNum in valueArray) {
+        CGFloat valueFloat = [valueNum floatValue];
+        max = MAX(valueFloat, max);
+    }
+    return ceil(max);
+}
+
+- (void)addAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *animateScale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+        animateScale.fromValue = [NSNumber numberWithFloat:0.f];
+        animateScale.toValue = [NSNumber numberWithFloat:1.0f];
+        
+        CABasicAnimation *animateMove = [CABasicAnimation animationWithKeyPath:@"position"];
+        animateMove.fromValue = [NSValue valueWithCGPoint:CGPointMake(_centerX, _centerY)];
+        animateMove.toValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
+        
+        CABasicAnimation *animateAlpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        animateAlpha.fromValue = [NSNumber numberWithFloat:0.f];
+        
+        CAAnimationGroup *aniGroup = [CAAnimationGroup animation];
+        aniGroup.duration = 1.f;
+        aniGroup.repeatCount = 1;
+        aniGroup.animations = [NSArray arrayWithObjects:animateScale,animateMove,animateAlpha, nil];
+        aniGroup.removedOnCompletion = YES;
+        
+        [_chartPlot addAnimation:aniGroup forKey:nil];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNRadarChartDataItem.h b/PNChartdemo/PNChart/PNRadarChartDataItem.h
new file mode 100755
index 0000000..e67429c
--- /dev/null
+++ b/PNChartdemo/PNChart/PNRadarChartDataItem.h
@@ -0,0 +1,19 @@
+//
+//  PNRadarChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface PNRadarChartDataItem : NSObject
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                      description:(NSString *)description;
+
+@property (nonatomic) CGFloat   value;
+@property (nonatomic,copy) NSString *textDescription;
+
+@end
diff --git a/PNChartdemo/PNChart/PNRadarChartDataItem.m b/PNChartdemo/PNChart/PNRadarChartDataItem.m
new file mode 100755
index 0000000..218ef6e
--- /dev/null
+++ b/PNChartdemo/PNChart/PNRadarChartDataItem.m
@@ -0,0 +1,29 @@
+//
+//  PNRadarChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import "PNRadarChartDataItem.h"
+
+@implementation PNRadarChartDataItem
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                      description:(NSString *)description {
+    PNRadarChartDataItem *item = [PNRadarChartDataItem new];
+    item.value = value;
+    item.textDescription = description;
+    return item;
+}
+
+- (void)setValue:(CGFloat)value {
+    if (value < 0) {
+        value = 0;
+        NSLog(@"Value value can not be negative");
+    }
+    _value = value;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChart.h b/PNChartdemo/PNChart/PNScatterChart.h
new file mode 100755
index 0000000..aa4eab8
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChart.h
@@ -0,0 +1,69 @@
+//
+//  PNScatterChart.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "PNChartDelegate.h"
+#import "PNGenericChart.h"
+#import "PNScatterChartData.h"
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChart : PNGenericChart
+
+@property (nonatomic, retain) id<PNChartDelegate> delegate;
+
+/** Array of `ScatterChartData` objects, one for each line. */
+@property (nonatomic) NSArray *chartData;
+
+/** Controls whether to show the coordinate axis. Default is NO. */
+@property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis;
+@property (nonatomic) UIColor *axisColor;
+@property (nonatomic) CGFloat axisWidth;
+
+/** String formatter for float values in x-axis/y-axis labels. If not set, defaults to @"%1.f" */
+@property (nonatomic, strong) NSString *xLabelFormat;
+@property (nonatomic, strong) NSString *yLabelFormat;
+
+/** Default is true. */
+@property (nonatomic) BOOL showLabel;
+
+/** Default is 18-point Avenir Medium. */
+@property (nonatomic) UIFont  *descriptionTextFont;
+
+/** Default is white. */
+@property (nonatomic) UIColor *descriptionTextColor;
+
+/** Default is black, with an alpha of 0.4. */
+@property (nonatomic) UIColor *descriptionTextShadowColor;
+
+/** Default is CGSizeMake(0, 1). */
+@property (nonatomic) CGSize   descriptionTextShadowOffset;
+
+/** Default is 1.0. */
+@property (nonatomic) NSTimeInterval duration;
+
+@property (nonatomic) CGFloat AxisX_minValue;
+@property (nonatomic) CGFloat AxisX_maxValue;
+
+@property (nonatomic) CGFloat AxisY_minValue;
+@property (nonatomic) CGFloat AxisY_maxValue;
+
+- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
+- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
+- (void) setAxisXLabel:(NSArray *)array;
+- (void) setAxisYLabel:(NSArray *)array;
+- (void) setup;
+- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color;
+
+/**
+ * Update Chart Value
+ */
+
+- (void)updateChartData:(NSArray *)data;
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChart.m b/PNChartdemo/PNChart/PNScatterChart.m
new file mode 100755
index 0000000..a16cf85
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChart.m
@@ -0,0 +1,445 @@
+//
+//  PNScatterChart.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+#import "PNScatterChartData.h"
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChart ()
+
+@property (nonatomic, weak) CAShapeLayer *pathLayer;
+@property (nonatomic, weak) NSMutableArray *verticalLineLayer;
+@property (nonatomic, weak) NSMutableArray *horizentalLinepathLayer;
+
+@property (nonatomic) CGPoint startPoint;
+
+@property (nonatomic) CGPoint startPointVectorX;
+@property (nonatomic) CGPoint endPointVecotrX;
+
+@property (nonatomic) CGPoint startPointVectorY;
+@property (nonatomic) CGPoint endPointVecotrY;
+
+@property (nonatomic) CGFloat vectorX_Steps;
+@property (nonatomic) CGFloat vectorY_Steps;
+
+@property (nonatomic) CGFloat vectorX_Size;
+@property (nonatomic) CGFloat vectorY_Size;
+
+@property (nonatomic) NSMutableArray *axisX_labels;
+@property (nonatomic) NSMutableArray *axisY_labels;
+
+@property (nonatomic) int AxisX_partNumber ;
+@property (nonatomic) int AxisY_partNumber ;
+
+@property (nonatomic) CGFloat AxisX_step ;
+@property (nonatomic) CGFloat AxisY_step ;
+
+@property (nonatomic) CGFloat AxisX_Margin;
+@property (nonatomic) CGFloat AxisY_Margin;
+
+@property (nonatomic) BOOL isForUpdate;
+
+@end
+
+
+@implementation PNScatterChart
+
+#pragma mark initialization
+
+- (id)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (void) setup
+{
+    [self vectorXSetup];
+    [self vectorYSetup];
+}
+
+- (void)setupDefaultValues
+{
+    [super setupDefaultValues];
+    
+    // Initialization code
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds   = YES;
+    _showLabel           = YES;
+    _isForUpdate         = NO;
+    self.userInteractionEnabled = YES;
+    
+    // Coordinate Axis Default Values
+    _showCoordinateAxis = YES;
+    _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f];
+    _axisWidth = 1.f;
+    
+    // Initialization code
+    _AxisX_Margin = 30 ;
+    _AxisY_Margin = 30 ;
+    
+//    self.frame = CGRectMake((SCREEN_WIDTH - self.frame.size.width) / 2, 200, self.frame.size.width, self.frame.size.height) ;
+    self.backgroundColor = [UIColor clearColor];
+    
+    _startPoint.y = self.frame.size.height - self.AxisY_Margin ;
+    _startPoint.x = self.AxisX_Margin ;
+    
+    _axisX_labels = [NSMutableArray array];
+    _axisY_labels = [NSMutableArray array];
+    
+    _descriptionTextColor = [UIColor blackColor];
+    _descriptionTextFont  = [UIFont fontWithName:@"Avenir-Medium" size:9.0];
+    _descriptionTextShadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
+    _descriptionTextShadowOffset =  CGSizeMake(0, 1);
+    _duration = 1.0;
+    
+}
+
+#pragma mark calculating axis
+
+- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
+{
+    _AxisX_minValue = minVal ;
+    _AxisX_maxValue = maxVal ;
+    _AxisX_partNumber = numberOfTicks - 1;
+    _AxisX_step = (float)((maxVal - minVal)/_AxisX_partNumber);
+    
+    NSString *LabelFormat = self.xLabelFormat ? : @"%1.f";
+    CGFloat tempValue = minVal ;
+    UILabel *label = [[UILabel alloc] init];
+    label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
+    [_axisX_labels addObject:label];
+    for (int i = 0 ; i < _AxisX_partNumber; i++) {
+        tempValue = tempValue + _AxisX_step;
+        UILabel *tempLabel = [[UILabel alloc] init];
+        tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
+        [_axisX_labels addObject:tempLabel];
+    }
+}
+
+- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
+{
+    _AxisY_minValue = minVal ;
+    _AxisY_maxValue = maxVal ;
+    _AxisY_partNumber = numberOfTicks - 1;
+    _AxisY_step = (float)((maxVal - minVal)/_AxisY_partNumber);
+    
+    NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
+    CGFloat tempValue = minVal ;
+    UILabel *label = [[UILabel alloc] init];
+    label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
+    [_axisY_labels addObject:label];
+    for (int i = 0 ; i < _AxisY_partNumber; i++) {
+        tempValue = tempValue + _AxisY_step;
+        UILabel *tempLabel = [[UILabel alloc] init];
+        tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
+        [_axisY_labels addObject:tempLabel];
+    }
+}
+
+- (NSArray*) getAxisMinMax:(NSArray*)xValues
+{
+    float min = [xValues[0] floatValue];
+    float max = [xValues[0] floatValue];
+    for (NSNumber *number in xValues)
+    {
+        if ([number floatValue] > max)
+            max = [number floatValue];
+        
+        if ([number floatValue] < min)
+            min = [number floatValue];
+    }
+    NSArray *result = @[[NSNumber numberWithFloat:min], [NSNumber numberWithFloat:max]];
+   
+    
+    return result;
+}
+
+- (void)setAxisXLabel:(NSArray *)array {
+    if(array.count == ++_AxisX_partNumber){
+        [_axisX_labels removeAllObjects];
+        for(int i=0;i<array.count;i++){
+            UILabel *label = [[UILabel alloc] init];
+            label.text = [array objectAtIndex:i];
+            [_axisX_labels addObject:label];
+        }
+    }
+}
+
+- (void)setAxisYLabel:(NSArray *)array {
+    if(array.count == ++_AxisY_partNumber){
+        [_axisY_labels removeAllObjects];
+        for(int i=0;i<array.count;i++){
+            UILabel *label = [[UILabel alloc] init];
+            label.text = [array objectAtIndex:i];
+            [_axisY_labels addObject:label];
+        }
+    }
+}
+
+- (void) vectorXSetup
+{
+    _AxisX_partNumber += 1;
+    _vectorX_Size = self.frame.size.width - (_AxisX_Margin) - 15 ;
+    _vectorX_Steps = (_vectorX_Size) / (_AxisX_partNumber) ;
+    _endPointVecotrX = CGPointMake(_startPoint.x + _vectorX_Size, _startPoint.y) ;
+    _startPointVectorX = _startPoint ;
+}
+
+- (void) vectorYSetup
+{
+    _AxisY_partNumber += 1;
+    _vectorY_Size = self.frame.size.height - (_AxisY_Margin) - 15;
+    _vectorY_Steps = (_vectorY_Size) / (_AxisY_partNumber);
+    _endPointVecotrY = CGPointMake(_startPoint.x, _startPoint.y - _vectorY_Size) ;
+    _startPointVectorY = _startPoint ;
+}
+
+- (void) showXLabel : (UILabel *) descriptionLabel InPosition : (CGPoint) point
+{
+    CGRect frame = CGRectMake(point.x, point.y, 30, 10);
+    descriptionLabel.frame = frame;
+    descriptionLabel.font = _descriptionTextFont;
+    descriptionLabel.textColor = _descriptionTextColor;
+    descriptionLabel.shadowColor = _descriptionTextShadowColor;
+    descriptionLabel.shadowOffset = _descriptionTextShadowOffset;
+    descriptionLabel.textAlignment = NSTextAlignmentCenter;
+    descriptionLabel.backgroundColor = [UIColor clearColor];
+    [self addSubview:descriptionLabel];
+}
+
+- (void)setChartData:(NSArray *)data
+{
+    __block CGFloat yFinilizeValue , xFinilizeValue;
+    __block CGFloat yValue , xValue;
+
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        if (self.displayAnimated) {
+            [NSThread sleepForTimeInterval:1];
+        }
+        // update UI on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            for (PNScatterChartData *chartData in data) {
+                for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+                    yValue = chartData.getData(i).y;
+                    xValue = chartData.getData(i).x;
+                    if (!(xValue >= _AxisX_minValue && xValue <= _AxisX_maxValue) || !(yValue >= _AxisY_minValue && yValue <= _AxisY_maxValue)) {
+                        NSLog(@"input is not in correct range.");
+                        exit(0);
+                    }
+                    xFinilizeValue = [self mappingIsForAxisX:true WithValue:xValue];
+                    yFinilizeValue = [self mappingIsForAxisX:false WithValue:yValue];
+                    CAShapeLayer *shape = [self drawingPointsForChartData:chartData AndWithX:xFinilizeValue AndWithY:yFinilizeValue];
+                    self.pathLayer = shape ;
+                    [self.layer addSublayer:self.pathLayer];
+                    
+                    [self addAnimationIfNeeded];
+                }
+            }
+        });
+    });
+}
+
+- (void)addAnimationIfNeeded{
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        pathAnimation.duration = _duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @(0.0f);
+        pathAnimation.toValue = @(1.0f);
+        pathAnimation.fillMode = kCAFillModeForwards;
+        self.layer.opacity = 1;
+        [self.pathLayer addAnimation:pathAnimation forKey:@"fade"];
+    }
+}
+
+- (CGFloat) mappingIsForAxisX : (BOOL) isForAxisX WithValue : (CGFloat) value{
+    
+    if (isForAxisX) {
+        float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
+        CGFloat xPos = temp + (((value - _AxisX_minValue)/_AxisX_step) * _vectorX_Steps) ;
+        return xPos;
+    }
+    else {
+        float temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
+        CGFloat yPos = temp - (((value - _AxisY_minValue) /_AxisY_step) * _vectorY_Steps);
+        return yPos;
+    }
+    return 0;
+}
+
+#pragma mark - Update Chart Data
+
+- (void)updateChartData:(NSArray *)data
+{
+    _chartData = data;
+
+    // will be work in future.
+}
+
+#pragma drawing methods
+
+- (void)drawRect:(CGRect)rect
+{
+    [super drawRect:rect];
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+        if (_showCoordinateAxis) {
+            CGContextSetStrokeColorWithColor(context, [_axisColor CGColor]);
+            CGContextSetLineWidth(context, _axisWidth);
+            //drawing x vector
+            CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            //drawing y vector
+            CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            //drawing x arrow vector
+            CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y + 3);
+            CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y - 3);
+            //drawing y arrow vector
+            CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x - 3, _endPointVecotrY.y + 5);
+            CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x + 3, _endPointVecotrY.y + 5);
+        }
+    
+    if (_showLabel) {
+        //drawing x steps vector and putting axis x labels
+        float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
+        for (int i = 0; i < _axisX_labels.count; i++) {
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(temp, _startPointVectorX.y - 2)];
+            [path addLineToPoint:CGPointMake(temp, _startPointVectorX.y + 3)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [_axisColor CGColor];
+            shapeLayer.lineWidth = _axisWidth;
+            shapeLayer.fillColor = [_axisColor CGColor];
+            [self.horizentalLinepathLayer addObject:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+            UILabel *lb = [_axisX_labels objectAtIndex:i] ;
+            [self showXLabel:lb InPosition:CGPointMake(temp - 15, _startPointVectorX.y + 10 )];
+            temp = temp + _vectorX_Steps ;
+        }
+        //drawing y steps vector and putting axis x labels
+        temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
+        for (int i = 0; i < _axisY_labels.count; i++) {
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(_startPointVectorY.x - 3, temp)];
+            [path addLineToPoint:CGPointMake( _startPointVectorY.x + 2, temp)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [_axisColor CGColor];
+            shapeLayer.lineWidth = _axisWidth;
+            shapeLayer.fillColor = [_axisColor CGColor];
+            [self.verticalLineLayer addObject:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+            UILabel *lb = [_axisY_labels objectAtIndex:i];
+            [self showXLabel:lb InPosition:CGPointMake(_startPointVectorY.x - 30, temp - 5)];
+            temp = temp - _vectorY_Steps ;
+        }
+    }
+    CGContextDrawPath(context, kCGPathStroke);
+}
+
+- (CAShapeLayer*) drawingPointsForChartData : (PNScatterChartData *) chartData AndWithX : (CGFloat) X AndWithY : (CGFloat) Y
+{
+    if (chartData.inflexionPointStyle == PNScatterChartPointStyleCircle) {
+        float radius = chartData.size;
+        CAShapeLayer *circle = [CAShapeLayer layer];
+        // Make a circular shape
+        circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(X - radius, Y - radius, 2.0*radius, 2.0*radius)
+                                                 cornerRadius:radius].CGPath;
+        // Configure the appearence of the circle
+        circle.fillColor = [chartData.fillColor CGColor];
+        circle.strokeColor = [chartData.strokeColor CGColor];
+        circle.lineWidth = 1;
+        
+        // Add to parent layer
+        return circle;
+    }
+    else if (chartData.inflexionPointStyle == PNScatterChartPointStyleSquare) {
+        float side = chartData.size;
+        CAShapeLayer *square = [CAShapeLayer layer];
+        // Make a circular shape
+        square.path = [UIBezierPath bezierPathWithRect:CGRectMake(X - (side/2) , Y - (side/2), side, side)].CGPath ;
+        // Configure the apperence of the circle
+        square.fillColor = [chartData.fillColor CGColor];
+        square.strokeColor = [chartData.strokeColor CGColor];
+        square.lineWidth = 1;
+        
+        // Add to parent layer
+        return square;
+    }
+    else {
+        // you cann add your own scatter chart point here
+    }
+    return nil ;
+}
+
+- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color{
+    
+    // call the same method on a background thread
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        if (self.displayAnimated) {
+            [NSThread sleepForTimeInterval:2];
+        }
+        // calculating start and end point
+        __block CGFloat startX = [self mappingIsForAxisX:true WithValue:startPoint.x];
+        __block CGFloat startY = [self mappingIsForAxisX:false WithValue:startPoint.y];
+        __block CGFloat endX = [self mappingIsForAxisX:true WithValue:endPoint.x];
+        __block CGFloat endY = [self mappingIsForAxisX:false WithValue:endPoint.y];
+        // update UI on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            // drawing path between two points
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(startX, startY)];
+            [path addLineToPoint:CGPointMake(endX, endY)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [color CGColor];
+            shapeLayer.lineWidth = lineWidth;
+            shapeLayer.fillColor = [color CGColor];
+            // adding animation to path
+            [self addStrokeEndAnimationIfNeededToLayer:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+        });
+    });
+}
+
+- (void)addStrokeEndAnimationIfNeededToLayer:(CAShapeLayer *)shapeLayer{
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        animateStrokeEnd.duration  = _duration;
+        animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f];
+        animateStrokeEnd.toValue   = [NSNumber numberWithFloat:1.0f];
+        [shapeLayer addAnimation:animateStrokeEnd forKey:nil];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChartData.h b/PNChartdemo/PNChart/PNScatterChartData.h
new file mode 100755
index 0000000..40b7b0e
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChartData.h
@@ -0,0 +1,38 @@
+//
+//  PNScatterChartData.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNScatterChartPointStyle) {
+    PNScatterChartPointStyleCircle = 0,
+    PNScatterChartPointStyleSquare = 1,
+};
+
+@class PNScatterChartDataItem;
+
+typedef PNScatterChartDataItem *(^LCScatterChartDataGetter)(NSUInteger item);
+
+@interface PNScatterChartData : NSObject
+
+@property (strong) UIColor *fillColor;
+@property (strong) UIColor *strokeColor;
+
+@property NSUInteger itemCount;
+@property (copy) LCScatterChartDataGetter getData;
+
+@property (nonatomic, assign) PNScatterChartPointStyle inflexionPointStyle;
+
+/**
+ * If PNLineChartPointStyle is circle, this returns the circle's diameter.
+ * If PNLineChartPointStyle is square, each point is a square with each side equal in length to this value.
+ */
+@property (nonatomic, assign) CGFloat size;
+
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChartData.m b/PNChartdemo/PNChart/PNScatterChartData.m
new file mode 100755
index 0000000..a53a5c2
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChartData.m
@@ -0,0 +1,31 @@
+//
+//  PNScatterChartData.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChartData.h"
+
+@implementation PNScatterChartData
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        [self setupDefaultValues];
+    }
+    
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    _inflexionPointStyle = PNScatterChartPointStyleCircle;
+    _fillColor = [UIColor grayColor];
+    _strokeColor = [UIColor clearColor];
+    _size = 3 ;
+}
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChartDataItem.h b/PNChartdemo/PNChart/PNScatterChartDataItem.h
new file mode 100755
index 0000000..f38ee4e
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChartDataItem.h
@@ -0,0 +1,19 @@
+//
+//  PNScatterChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNScatterChartDataItem : NSObject
+
++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y;
+
+@property (readonly) CGFloat x; // should be within the x range
+@property (readonly) CGFloat y; // should be within the y range
+
+@end
diff --git a/PNChartdemo/PNChart/PNScatterChartDataItem.m b/PNChartdemo/PNChart/PNScatterChartDataItem.m
new file mode 100755
index 0000000..a454459
--- /dev/null
+++ b/PNChartdemo/PNChart/PNScatterChartDataItem.m
@@ -0,0 +1,37 @@
+//
+//  PNScatterChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChartDataItem ()
+
+- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y;
+
+@property (readwrite) CGFloat x; // should be within the x range
+@property (readwrite) CGFloat y; // should be within the y range
+
+@end
+
+@implementation PNScatterChartDataItem
+
++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y
+{
+    return [[PNScatterChartDataItem alloc] initWithX:x AndWithY:y];
+}
+
+- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y
+{
+    if ((self = [super init])) {
+        self.x = x;
+        self.y = y;
+    }
+    
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo.xcodeproj/project.pbxproj b/PNChartdemo/PNChartdemo.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..651d89c
--- /dev/null
+++ b/PNChartdemo/PNChartdemo.xcodeproj/project.pbxproj
@@ -0,0 +1,479 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		E56E9F2E1E68F54300412830 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F2D1E68F54300412830 /* main.m */; };
+		E56E9F311E68F54300412830 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F301E68F54300412830 /* AppDelegate.m */; };
+		E56E9F341E68F54300412830 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F331E68F54300412830 /* ViewController.m */; };
+		E56E9F371E68F54300412830 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E56E9F351E68F54300412830 /* Main.storyboard */; };
+		E56E9F391E68F54300412830 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E56E9F381E68F54300412830 /* Assets.xcassets */; };
+		E56E9F3C1E68F54300412830 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E56E9F3A1E68F54300412830 /* LaunchScreen.storyboard */; };
+		E56E9F661E68F55F00412830 /* PNBar.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F451E68F55F00412830 /* PNBar.m */; };
+		E56E9F671E68F55F00412830 /* PNBarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F471E68F55F00412830 /* PNBarChart.m */; };
+		E56E9F681E68F55F00412830 /* PNChartLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F4B1E68F55F00412830 /* PNChartLabel.m */; };
+		E56E9F691E68F55F00412830 /* PNCircleChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F4D1E68F55F00412830 /* PNCircleChart.m */; };
+		E56E9F6A1E68F55F00412830 /* PNColor.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F4F1E68F55F00412830 /* PNColor.m */; };
+		E56E9F6B1E68F55F00412830 /* PNGenericChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F511E68F55F00412830 /* PNGenericChart.m */; };
+		E56E9F6C1E68F55F00412830 /* PNLineChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F531E68F55F00412830 /* PNLineChart.m */; };
+		E56E9F6D1E68F55F00412830 /* PNLineChartData.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F551E68F55F00412830 /* PNLineChartData.m */; };
+		E56E9F6E1E68F55F00412830 /* PNLineChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F571E68F55F00412830 /* PNLineChartDataItem.m */; };
+		E56E9F6F1E68F55F00412830 /* PNPieChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F591E68F55F00412830 /* PNPieChart.m */; };
+		E56E9F701E68F55F00412830 /* PNPieChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F5B1E68F55F00412830 /* PNPieChartDataItem.m */; };
+		E56E9F711E68F55F00412830 /* PNRadarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F5D1E68F55F00412830 /* PNRadarChart.m */; };
+		E56E9F721E68F55F00412830 /* PNRadarChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F5F1E68F55F00412830 /* PNRadarChartDataItem.m */; };
+		E56E9F731E68F55F00412830 /* PNScatterChart.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F611E68F55F00412830 /* PNScatterChart.m */; };
+		E56E9F741E68F55F00412830 /* PNScatterChartData.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F631E68F55F00412830 /* PNScatterChartData.m */; };
+		E56E9F751E68F55F00412830 /* PNScatterChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F651E68F55F00412830 /* PNScatterChartDataItem.m */; };
+		E56E9F781E68F59F00412830 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E56E9F771E68F59F00412830 /* CoreGraphics.framework */; };
+		E56E9F7A1E68F5A900412830 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E56E9F791E68F5A900412830 /* QuartzCore.framework */; };
+		E56E9F7C1E68F5B300412830 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E56E9F7B1E68F5B300412830 /* UIKit.framework */; };
+		E56E9F7E1E68F5B800412830 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E56E9F7D1E68F5B800412830 /* Foundation.framework */; };
+		E56E9F861E68F84700412830 /* UICountingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F851E68F84700412830 /* UICountingLabel.m */; };
+		E56E9F891E68F89200412830 /* PCChartsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F881E68F89200412830 /* PCChartsTableViewController.m */; };
+		E56E9F8C1E68F8F600412830 /* PCChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E56E9F8B1E68F8F600412830 /* PCChartViewController.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		E56E9F291E68F54300412830 /* PNChartdemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PNChartdemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		E56E9F2D1E68F54300412830 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		E56E9F2F1E68F54300412830 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		E56E9F301E68F54300412830 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		E56E9F321E68F54300412830 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
+		E56E9F331E68F54300412830 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
+		E56E9F361E68F54300412830 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+		E56E9F381E68F54300412830 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		E56E9F3B1E68F54300412830 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		E56E9F3D1E68F54300412830 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		E56E9F441E68F55F00412830 /* PNBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNBar.h; sourceTree = "<group>"; };
+		E56E9F451E68F55F00412830 /* PNBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNBar.m; sourceTree = "<group>"; };
+		E56E9F461E68F55F00412830 /* PNBarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNBarChart.h; sourceTree = "<group>"; };
+		E56E9F471E68F55F00412830 /* PNBarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNBarChart.m; sourceTree = "<group>"; };
+		E56E9F481E68F55F00412830 /* PNChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNChart.h; sourceTree = "<group>"; };
+		E56E9F491E68F55F00412830 /* PNChartDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNChartDelegate.h; sourceTree = "<group>"; };
+		E56E9F4A1E68F55F00412830 /* PNChartLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNChartLabel.h; sourceTree = "<group>"; };
+		E56E9F4B1E68F55F00412830 /* PNChartLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNChartLabel.m; sourceTree = "<group>"; };
+		E56E9F4C1E68F55F00412830 /* PNCircleChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNCircleChart.h; sourceTree = "<group>"; };
+		E56E9F4D1E68F55F00412830 /* PNCircleChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNCircleChart.m; sourceTree = "<group>"; };
+		E56E9F4E1E68F55F00412830 /* PNColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNColor.h; sourceTree = "<group>"; };
+		E56E9F4F1E68F55F00412830 /* PNColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNColor.m; sourceTree = "<group>"; };
+		E56E9F501E68F55F00412830 /* PNGenericChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNGenericChart.h; sourceTree = "<group>"; };
+		E56E9F511E68F55F00412830 /* PNGenericChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNGenericChart.m; sourceTree = "<group>"; };
+		E56E9F521E68F55F00412830 /* PNLineChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNLineChart.h; sourceTree = "<group>"; };
+		E56E9F531E68F55F00412830 /* PNLineChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNLineChart.m; sourceTree = "<group>"; };
+		E56E9F541E68F55F00412830 /* PNLineChartData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNLineChartData.h; sourceTree = "<group>"; };
+		E56E9F551E68F55F00412830 /* PNLineChartData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNLineChartData.m; sourceTree = "<group>"; };
+		E56E9F561E68F55F00412830 /* PNLineChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNLineChartDataItem.h; sourceTree = "<group>"; };
+		E56E9F571E68F55F00412830 /* PNLineChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNLineChartDataItem.m; sourceTree = "<group>"; };
+		E56E9F581E68F55F00412830 /* PNPieChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNPieChart.h; sourceTree = "<group>"; };
+		E56E9F591E68F55F00412830 /* PNPieChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNPieChart.m; sourceTree = "<group>"; };
+		E56E9F5A1E68F55F00412830 /* PNPieChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNPieChartDataItem.h; sourceTree = "<group>"; };
+		E56E9F5B1E68F55F00412830 /* PNPieChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNPieChartDataItem.m; sourceTree = "<group>"; };
+		E56E9F5C1E68F55F00412830 /* PNRadarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNRadarChart.h; sourceTree = "<group>"; };
+		E56E9F5D1E68F55F00412830 /* PNRadarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNRadarChart.m; sourceTree = "<group>"; };
+		E56E9F5E1E68F55F00412830 /* PNRadarChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNRadarChartDataItem.h; sourceTree = "<group>"; };
+		E56E9F5F1E68F55F00412830 /* PNRadarChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNRadarChartDataItem.m; sourceTree = "<group>"; };
+		E56E9F601E68F55F00412830 /* PNScatterChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNScatterChart.h; sourceTree = "<group>"; };
+		E56E9F611E68F55F00412830 /* PNScatterChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNScatterChart.m; sourceTree = "<group>"; };
+		E56E9F621E68F55F00412830 /* PNScatterChartData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNScatterChartData.h; sourceTree = "<group>"; };
+		E56E9F631E68F55F00412830 /* PNScatterChartData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNScatterChartData.m; sourceTree = "<group>"; };
+		E56E9F641E68F55F00412830 /* PNScatterChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNScatterChartDataItem.h; sourceTree = "<group>"; };
+		E56E9F651E68F55F00412830 /* PNScatterChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNScatterChartDataItem.m; sourceTree = "<group>"; };
+		E56E9F771E68F59F00412830 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		E56E9F791E68F5A900412830 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		E56E9F7B1E68F5B300412830 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		E56E9F7D1E68F5B800412830 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		E56E9F7F1E68F64800412830 /* PNChartDemo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PNChartDemo-Prefix.pch"; sourceTree = "<group>"; };
+		E56E9F841E68F84700412830 /* UICountingLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UICountingLabel.h; sourceTree = "<group>"; };
+		E56E9F851E68F84700412830 /* UICountingLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UICountingLabel.m; sourceTree = "<group>"; };
+		E56E9F871E68F89200412830 /* PCChartsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCChartsTableViewController.h; sourceTree = "<group>"; };
+		E56E9F881E68F89200412830 /* PCChartsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PCChartsTableViewController.m; sourceTree = "<group>"; };
+		E56E9F8A1E68F8F600412830 /* PCChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCChartViewController.h; sourceTree = "<group>"; };
+		E56E9F8B1E68F8F600412830 /* PCChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PCChartViewController.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		E56E9F261E68F54300412830 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E56E9F7E1E68F5B800412830 /* Foundation.framework in Frameworks */,
+				E56E9F7C1E68F5B300412830 /* UIKit.framework in Frameworks */,
+				E56E9F7A1E68F5A900412830 /* QuartzCore.framework in Frameworks */,
+				E56E9F781E68F59F00412830 /* CoreGraphics.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		E56E9F201E68F54300412830 = {
+			isa = PBXGroup;
+			children = (
+				E56E9F431E68F55F00412830 /* PNChart */,
+				E56E9F2B1E68F54300412830 /* PNChartdemo */,
+				E56E9F2A1E68F54300412830 /* Products */,
+				E56E9F761E68F59E00412830 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		E56E9F2A1E68F54300412830 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F291E68F54300412830 /* PNChartdemo.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		E56E9F2B1E68F54300412830 /* PNChartdemo */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F8A1E68F8F600412830 /* PCChartViewController.h */,
+				E56E9F8B1E68F8F600412830 /* PCChartViewController.m */,
+				E56E9F871E68F89200412830 /* PCChartsTableViewController.h */,
+				E56E9F881E68F89200412830 /* PCChartsTableViewController.m */,
+				E56E9F831E68F84700412830 /* UICountingLabel */,
+				E56E9F2F1E68F54300412830 /* AppDelegate.h */,
+				E56E9F301E68F54300412830 /* AppDelegate.m */,
+				E56E9F321E68F54300412830 /* ViewController.h */,
+				E56E9F331E68F54300412830 /* ViewController.m */,
+				E56E9F351E68F54300412830 /* Main.storyboard */,
+				E56E9F381E68F54300412830 /* Assets.xcassets */,
+				E56E9F3A1E68F54300412830 /* LaunchScreen.storyboard */,
+				E56E9F2C1E68F54300412830 /* Supporting Files */,
+			);
+			path = PNChartdemo;
+			sourceTree = "<group>";
+		};
+		E56E9F2C1E68F54300412830 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F7F1E68F64800412830 /* PNChartDemo-Prefix.pch */,
+				E56E9F3D1E68F54300412830 /* Info.plist */,
+				E56E9F2D1E68F54300412830 /* main.m */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		E56E9F431E68F55F00412830 /* PNChart */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F441E68F55F00412830 /* PNBar.h */,
+				E56E9F451E68F55F00412830 /* PNBar.m */,
+				E56E9F461E68F55F00412830 /* PNBarChart.h */,
+				E56E9F471E68F55F00412830 /* PNBarChart.m */,
+				E56E9F481E68F55F00412830 /* PNChart.h */,
+				E56E9F491E68F55F00412830 /* PNChartDelegate.h */,
+				E56E9F4A1E68F55F00412830 /* PNChartLabel.h */,
+				E56E9F4B1E68F55F00412830 /* PNChartLabel.m */,
+				E56E9F4C1E68F55F00412830 /* PNCircleChart.h */,
+				E56E9F4D1E68F55F00412830 /* PNCircleChart.m */,
+				E56E9F4E1E68F55F00412830 /* PNColor.h */,
+				E56E9F4F1E68F55F00412830 /* PNColor.m */,
+				E56E9F501E68F55F00412830 /* PNGenericChart.h */,
+				E56E9F511E68F55F00412830 /* PNGenericChart.m */,
+				E56E9F521E68F55F00412830 /* PNLineChart.h */,
+				E56E9F531E68F55F00412830 /* PNLineChart.m */,
+				E56E9F541E68F55F00412830 /* PNLineChartData.h */,
+				E56E9F551E68F55F00412830 /* PNLineChartData.m */,
+				E56E9F561E68F55F00412830 /* PNLineChartDataItem.h */,
+				E56E9F571E68F55F00412830 /* PNLineChartDataItem.m */,
+				E56E9F581E68F55F00412830 /* PNPieChart.h */,
+				E56E9F591E68F55F00412830 /* PNPieChart.m */,
+				E56E9F5A1E68F55F00412830 /* PNPieChartDataItem.h */,
+				E56E9F5B1E68F55F00412830 /* PNPieChartDataItem.m */,
+				E56E9F5C1E68F55F00412830 /* PNRadarChart.h */,
+				E56E9F5D1E68F55F00412830 /* PNRadarChart.m */,
+				E56E9F5E1E68F55F00412830 /* PNRadarChartDataItem.h */,
+				E56E9F5F1E68F55F00412830 /* PNRadarChartDataItem.m */,
+				E56E9F601E68F55F00412830 /* PNScatterChart.h */,
+				E56E9F611E68F55F00412830 /* PNScatterChart.m */,
+				E56E9F621E68F55F00412830 /* PNScatterChartData.h */,
+				E56E9F631E68F55F00412830 /* PNScatterChartData.m */,
+				E56E9F641E68F55F00412830 /* PNScatterChartDataItem.h */,
+				E56E9F651E68F55F00412830 /* PNScatterChartDataItem.m */,
+			);
+			path = PNChart;
+			sourceTree = "<group>";
+		};
+		E56E9F761E68F59E00412830 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F7D1E68F5B800412830 /* Foundation.framework */,
+				E56E9F7B1E68F5B300412830 /* UIKit.framework */,
+				E56E9F791E68F5A900412830 /* QuartzCore.framework */,
+				E56E9F771E68F59F00412830 /* CoreGraphics.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		E56E9F831E68F84700412830 /* UICountingLabel */ = {
+			isa = PBXGroup;
+			children = (
+				E56E9F841E68F84700412830 /* UICountingLabel.h */,
+				E56E9F851E68F84700412830 /* UICountingLabel.m */,
+			);
+			path = UICountingLabel;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		E56E9F281E68F54300412830 /* PNChartdemo */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = E56E9F401E68F54300412830 /* Build configuration list for PBXNativeTarget "PNChartdemo" */;
+			buildPhases = (
+				E56E9F251E68F54300412830 /* Sources */,
+				E56E9F261E68F54300412830 /* Frameworks */,
+				E56E9F271E68F54300412830 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = PNChartdemo;
+			productName = PNChartdemo;
+			productReference = E56E9F291E68F54300412830 /* PNChartdemo.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		E56E9F211E68F54300412830 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0820;
+				ORGANIZATIONNAME = WindShan;
+				TargetAttributes = {
+					E56E9F281E68F54300412830 = {
+						CreatedOnToolsVersion = 8.2.1;
+						DevelopmentTeam = VGXA77XL6T;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = E56E9F241E68F54300412830 /* Build configuration list for PBXProject "PNChartdemo" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = E56E9F201E68F54300412830;
+			productRefGroup = E56E9F2A1E68F54300412830 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				E56E9F281E68F54300412830 /* PNChartdemo */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		E56E9F271E68F54300412830 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E56E9F3C1E68F54300412830 /* LaunchScreen.storyboard in Resources */,
+				E56E9F391E68F54300412830 /* Assets.xcassets in Resources */,
+				E56E9F371E68F54300412830 /* Main.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		E56E9F251E68F54300412830 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E56E9F6C1E68F55F00412830 /* PNLineChart.m in Sources */,
+				E56E9F671E68F55F00412830 /* PNBarChart.m in Sources */,
+				E56E9F6A1E68F55F00412830 /* PNColor.m in Sources */,
+				E56E9F891E68F89200412830 /* PCChartsTableViewController.m in Sources */,
+				E56E9F711E68F55F00412830 /* PNRadarChart.m in Sources */,
+				E56E9F721E68F55F00412830 /* PNRadarChartDataItem.m in Sources */,
+				E56E9F341E68F54300412830 /* ViewController.m in Sources */,
+				E56E9F661E68F55F00412830 /* PNBar.m in Sources */,
+				E56E9F741E68F55F00412830 /* PNScatterChartData.m in Sources */,
+				E56E9F6E1E68F55F00412830 /* PNLineChartDataItem.m in Sources */,
+				E56E9F681E68F55F00412830 /* PNChartLabel.m in Sources */,
+				E56E9F311E68F54300412830 /* AppDelegate.m in Sources */,
+				E56E9F751E68F55F00412830 /* PNScatterChartDataItem.m in Sources */,
+				E56E9F701E68F55F00412830 /* PNPieChartDataItem.m in Sources */,
+				E56E9F2E1E68F54300412830 /* main.m in Sources */,
+				E56E9F6D1E68F55F00412830 /* PNLineChartData.m in Sources */,
+				E56E9F731E68F55F00412830 /* PNScatterChart.m in Sources */,
+				E56E9F691E68F55F00412830 /* PNCircleChart.m in Sources */,
+				E56E9F8C1E68F8F600412830 /* PCChartViewController.m in Sources */,
+				E56E9F861E68F84700412830 /* UICountingLabel.m in Sources */,
+				E56E9F6F1E68F55F00412830 /* PNPieChart.m in Sources */,
+				E56E9F6B1E68F55F00412830 /* PNGenericChart.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		E56E9F351E68F54300412830 /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				E56E9F361E68F54300412830 /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+		E56E9F3A1E68F54300412830 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				E56E9F3B1E68F54300412830 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		E56E9F3E1E68F54300412830 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		E56E9F3F1E68F54300412830 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		E56E9F411E68F54300412830 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				DEVELOPMENT_TEAM = VGXA77XL6T;
+				GCC_PREFIX_HEADER = "PNChartdemo/PNChartDemo-Prefix.pch";
+				INFOPLIST_FILE = PNChartdemo/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.moral.PNChartdemo.PNChartdemo;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		E56E9F421E68F54300412830 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				DEVELOPMENT_TEAM = VGXA77XL6T;
+				GCC_PREFIX_HEADER = "PNChartdemo/PNChartDemo-Prefix.pch";
+				INFOPLIST_FILE = PNChartdemo/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.moral.PNChartdemo.PNChartdemo;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		E56E9F241E68F54300412830 /* Build configuration list for PBXProject "PNChartdemo" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				E56E9F3E1E68F54300412830 /* Debug */,
+				E56E9F3F1E68F54300412830 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		E56E9F401E68F54300412830 /* Build configuration list for PBXNativeTarget "PNChartdemo" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				E56E9F411E68F54300412830 /* Debug */,
+				E56E9F421E68F54300412830 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = E56E9F211E68F54300412830 /* Project object */;
+}
diff --git a/camerademo/camerademo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 69%
rename from camerademo/camerademo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index ac29a49..3674b57 100644
--- a/camerademo/camerademo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
 <Workspace
    version = "1.0">
    <FileRef
-      location = "self:camerademo.xcodeproj">
+      location = "self:PNChartdemo.xcodeproj">
    </FileRef>
 </Workspace>
diff --git a/PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate b/PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..ee124fb
--- /dev/null
+++ b/PNChartdemo/PNChartdemo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate
Binary files differ
diff --git a/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
new file mode 100644
index 0000000..ce2e85d
--- /dev/null
+++ b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   type = "1"
+   version = "2.0">
+   <Breakpoints>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "PNChartdemo/PCChartViewController.m"
+            timestampString = "510197037.819375"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "403"
+            endingLineNumber = "403"
+            landmarkName = "-rightSwitchChanged:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "PNChartdemo/PCChartViewController.m"
+            timestampString = "510197037.819375"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "412"
+            endingLineNumber = "412"
+            landmarkName = "-centerSwitchChanged:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "PNChartdemo/PCChartViewController.m"
+            timestampString = "510197037.819375"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "433"
+            endingLineNumber = "433"
+            landmarkName = "-leftSwitchChanged:"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+   </Breakpoints>
+</Bucket>
diff --git a/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/PNChartdemo.xcscheme b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/PNChartdemo.xcscheme
new file mode 100644
index 0000000..8666a26
--- /dev/null
+++ b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/PNChartdemo.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0820"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "E56E9F281E68F54300412830"
+               BuildableName = "PNChartdemo.app"
+               BlueprintName = "PNChartdemo"
+               ReferencedContainer = "container:PNChartdemo.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "E56E9F281E68F54300412830"
+            BuildableName = "PNChartdemo.app"
+            BlueprintName = "PNChartdemo"
+            ReferencedContainer = "container:PNChartdemo.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "E56E9F281E68F54300412830"
+            BuildableName = "PNChartdemo.app"
+            BlueprintName = "PNChartdemo"
+            ReferencedContainer = "container:PNChartdemo.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "E56E9F281E68F54300412830"
+            BuildableName = "PNChartdemo.app"
+            BlueprintName = "PNChartdemo"
+            ReferencedContainer = "container:PNChartdemo.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist
similarity index 84%
rename from camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist
rename to PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist
index 01e9d0f..d85d839 100644
--- a/camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/PNChartdemo/PNChartdemo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -4,7 +4,7 @@
 <dict>
 	<key>SchemeUserState</key>
 	<dict>
-		<key>camerademo.xcscheme</key>
+		<key>PNChartdemo.xcscheme</key>
 		<dict>
 			<key>orderHint</key>
 			<integer>0</integer>
@@ -12,7 +12,7 @@
 	</dict>
 	<key>SuppressBuildableAutocreation</key>
 	<dict>
-		<key>E52F59EA1E5C21890084B3E2</key>
+		<key>E56E9F281E68F54300412830</key>
 		<dict>
 			<key>primary</key>
 			<true/>
diff --git a/camerademo/camerademo/AppDelegate.h b/PNChartdemo/PNChartdemo/AppDelegate.h
similarity index 80%
rename from camerademo/camerademo/AppDelegate.h
rename to PNChartdemo/PNChartdemo/AppDelegate.h
index ca2a55e..e933d75 100644
--- a/camerademo/camerademo/AppDelegate.h
+++ b/PNChartdemo/PNChartdemo/AppDelegate.h
@@ -1,8 +1,8 @@
 //
 //  AppDelegate.h
-//  camerademo
+//  PNChartdemo
 //
-//  Created by WindShan on 2017/2/21.
+//  Created by WindShan on 2017/3/3.
 //  Copyright �� 2017��� WindShan. All rights reserved.
 //
 
diff --git a/camerademo/camerademo/AppDelegate.m b/PNChartdemo/PNChartdemo/AppDelegate.m
similarity index 96%
rename from camerademo/camerademo/AppDelegate.m
rename to PNChartdemo/PNChartdemo/AppDelegate.m
index c5b854e..93c0cbb 100644
--- a/camerademo/camerademo/AppDelegate.m
+++ b/PNChartdemo/PNChartdemo/AppDelegate.m
@@ -1,8 +1,8 @@
 //
 //  AppDelegate.m
-//  camerademo
+//  PNChartdemo
 //
-//  Created by WindShan on 2017/2/21.
+//  Created by WindShan on 2017/3/3.
 //  Copyright �� 2017��� WindShan. All rights reserved.
 //
 
diff --git a/camerademo/camerademo/Assets.xcassets/AppIcon.appiconset/Contents.json b/PNChartdemo/PNChartdemo/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from camerademo/camerademo/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to PNChartdemo/PNChartdemo/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/camerademo/camerademo/Base.lproj/LaunchScreen.storyboard b/PNChartdemo/PNChartdemo/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from camerademo/camerademo/Base.lproj/LaunchScreen.storyboard
rename to PNChartdemo/PNChartdemo/Base.lproj/LaunchScreen.storyboard
diff --git a/PNChartdemo/PNChartdemo/Base.lproj/Main.storyboard b/PNChartdemo/PNChartdemo/Base.lproj/Main.storyboard
new file mode 100755
index 0000000..f75524f
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/Base.lproj/Main.storyboard
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="9Rt-UT-IxH">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
+        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--PNChart-->
+        <scene sceneID="lC9-iu-Smd">
+            <objects>
+                <viewController id="Tha-Wr-sPW" customClass="PCChartViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="znr-YO-4a4"/>
+                        <viewControllerLayoutGuide type="bottom" id="61B-jM-QAH"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="PPb-b8-nBo">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <subviews>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="L3F-13-Wf5">
+                                <rect key="frame" x="140" y="364" width="95" height="30"/>
+                                <state key="normal" title="Change Value">
+                                    <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                </state>
+                                <connections>
+                                    <action selector="changeValue:" destination="Tha-Wr-sPW" eventType="touchUpInside" id="zeG-Cp-Wjs"/>
+                                </connections>
+                            </button>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FUU-vZ-jMd">
+                                <rect key="frame" x="159" y="81" width="57" height="32"/>
+                                <fontDescription key="fontDescription" name="Avenir-Medium" family="Avenir" pointSize="23"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Percentage" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IKu-qh-ksi">
+                                <rect key="frame" x="16" y="539" width="88" height="21"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Show Labels" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ifm-a9-Wkq">
+                                <rect key="frame" x="260" y="538" width="99" height="21"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="99" id="KZW-Ru-GZO"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="kav-3r-blI">
+                                <rect key="frame" x="16" y="434" width="51" height="31"/>
+                                <connections>
+                                    <action selector="centerSwitchChanged:" destination="Tha-Wr-sPW" eventType="valueChanged" id="ETI-hb-d8F"/>
+                                </connections>
+                            </switch>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Multiple Selection" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sMF-o9-dZX">
+                                <rect key="frame" x="16" y="471" width="137" height="21"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ORA-mb-hJl">
+                                <rect key="frame" x="16" y="500" width="51" height="31"/>
+                                <connections>
+                                    <action selector="leftSwitchChanged:" destination="Tha-Wr-sPW" eventType="valueChanged" id="q9T-QK-Sas"/>
+                                </connections>
+                            </switch>
+                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mnm-Is-oih" userLabel="Animations Switch">
+                                <rect key="frame" x="310" y="434" width="51" height="31"/>
+                                <connections>
+                                    <action selector="animationsSwitchChanged:" destination="Tha-Wr-sPW" eventType="valueChanged" id="lC4-5M-rlC"/>
+                                </connections>
+                            </switch>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Animations" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lc1-oP-FNw">
+                                <rect key="frame" x="273" y="471" width="86" height="21"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qR7-40-7ir">
+                                <rect key="frame" x="310" y="500" width="51" height="31"/>
+                                <connections>
+                                    <action selector="rightSwitchChanged:" destination="Tha-Wr-sPW" eventType="valueChanged" id="n6V-lL-r8Q"/>
+                                </connections>
+                            </switch>
+                        </subviews>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <constraints>
+                            <constraint firstItem="Mnm-Is-oih" firstAttribute="centerY" secondItem="kav-3r-blI" secondAttribute="centerY" id="0NI-PI-ATH"/>
+                            <constraint firstItem="ORA-mb-hJl" firstAttribute="centerY" secondItem="qR7-40-7ir" secondAttribute="centerY" id="7c9-My-TTD"/>
+                            <constraint firstItem="IKu-qh-ksi" firstAttribute="top" secondItem="ORA-mb-hJl" secondAttribute="bottom" constant="8" id="7vb-uB-f1x"/>
+                            <constraint firstItem="Ifm-a9-Wkq" firstAttribute="top" secondItem="qR7-40-7ir" secondAttribute="bottom" constant="7" id="9ET-Wq-Yen"/>
+                            <constraint firstItem="qR7-40-7ir" firstAttribute="top" secondItem="lc1-oP-FNw" secondAttribute="bottom" constant="8" id="A54-NU-I6K"/>
+                            <constraint firstItem="FUU-vZ-jMd" firstAttribute="top" secondItem="znr-YO-4a4" secondAttribute="bottom" constant="17" id="DLv-qJ-h7R"/>
+                            <constraint firstItem="sMF-o9-dZX" firstAttribute="top" secondItem="kav-3r-blI" secondAttribute="bottom" constant="6" id="Fy1-r9-rOd"/>
+                            <constraint firstItem="Ifm-a9-Wkq" firstAttribute="trailing" secondItem="qR7-40-7ir" secondAttribute="trailing" id="Im7-AC-dup"/>
+                            <constraint firstItem="ORA-mb-hJl" firstAttribute="top" secondItem="sMF-o9-dZX" secondAttribute="bottom" constant="8" symbolic="YES" id="K0Z-Kz-m2p"/>
+                            <constraint firstAttribute="trailingMargin" secondItem="qR7-40-7ir" secondAttribute="trailing" id="KZ9-eM-6oW"/>
+                            <constraint firstItem="kav-3r-blI" firstAttribute="leading" secondItem="PPb-b8-nBo" secondAttribute="leadingMargin" id="KrJ-mU-I6l"/>
+                            <constraint firstAttribute="centerX" secondItem="FUU-vZ-jMd" secondAttribute="centerX" id="YGT-a5-Zka"/>
+                            <constraint firstItem="lc1-oP-FNw" firstAttribute="trailing" secondItem="Mnm-Is-oih" secondAttribute="trailing" id="YrP-Jx-D1J"/>
+                            <constraint firstItem="lc1-oP-FNw" firstAttribute="top" secondItem="Mnm-Is-oih" secondAttribute="bottom" constant="6" id="Zsm-LK-7NY"/>
+                            <constraint firstAttribute="trailingMargin" secondItem="Mnm-Is-oih" secondAttribute="trailing" id="bnI-nC-1qS"/>
+                            <constraint firstItem="kav-3r-blI" firstAttribute="top" secondItem="L3F-13-Wf5" secondAttribute="bottom" constant="40" id="eO9-bU-rZY"/>
+                            <constraint firstItem="L3F-13-Wf5" firstAttribute="top" secondItem="znr-YO-4a4" secondAttribute="bottom" constant="300" id="ewm-kv-p8k"/>
+                            <constraint firstItem="IKu-qh-ksi" firstAttribute="leading" secondItem="PPb-b8-nBo" secondAttribute="leadingMargin" id="m9a-Ug-SfK"/>
+                            <constraint firstItem="ORA-mb-hJl" firstAttribute="leading" secondItem="PPb-b8-nBo" secondAttribute="leadingMargin" id="oZO-il-Fd5"/>
+                            <constraint firstItem="sMF-o9-dZX" firstAttribute="leading" secondItem="kav-3r-blI" secondAttribute="leading" id="qtt-KE-YfT"/>
+                            <constraint firstAttribute="centerX" secondItem="L3F-13-Wf5" secondAttribute="centerX" id="zXw-WV-mro"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="PNChart" id="Ukg-Sg-E2z"/>
+                    <connections>
+                        <outlet property="animationsSwitch" destination="Mnm-Is-oih" id="haB-27-exI"/>
+                        <outlet property="centerSwitch" destination="kav-3r-blI" id="aDA-mR-FhR"/>
+                        <outlet property="centerSwitchLabel" destination="sMF-o9-dZX" id="Epf-8v-NeL"/>
+                        <outlet property="changeValueButton" destination="L3F-13-Wf5" id="JnI-y3-Xpj"/>
+                        <outlet property="leftLabel" destination="IKu-qh-ksi" id="CPy-oy-qCP"/>
+                        <outlet property="leftSwitch" destination="ORA-mb-hJl" id="u1M-2f-6P1"/>
+                        <outlet property="rightLabel" destination="Ifm-a9-Wkq" id="QhE-j2-qpe"/>
+                        <outlet property="rightSwitch" destination="qR7-40-7ir" id="noL-6R-d3a"/>
+                        <outlet property="titleLabel" destination="FUU-vZ-jMd" id="dA3-KC-Ht4"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="kDa-u3-t6i" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="536" y="31"/>
+        </scene>
+        <!--PNChart-->
+        <scene sceneID="pBo-qW-N8B">
+            <objects>
+                <tableViewController id="cc5-BF-Ga2" customClass="PCChartsTableViewController" sceneMemberID="viewController">
+                    <tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="EAk-8x-zLw">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <sections>
+                            <tableViewSection id="Rtv-33-iAC">
+                                <cells>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="dtA-8k-dgn" style="IBUITableViewCellStyleDefault" id="irc-98-Qkg">
+                                        <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="irc-98-Qkg" id="QVQ-E4-AgU">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="LineChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dtA-8k-dgn">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="lineChart" id="XHj-XM-h67"/>
+                                        </connections>
+                                    </tableViewCell>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="sGJ-nJ-Evy" style="IBUITableViewCellStyleDefault" id="uiU-qo-XNI">
+                                        <rect key="frame" x="0.0" y="44" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="uiU-qo-XNI" id="QSW-pF-BtE">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="BarChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="sGJ-nJ-Evy">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="barChart" id="BAm-LA-QbM"/>
+                                        </connections>
+                                    </tableViewCell>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="Bn9-8g-5UP" style="IBUITableViewCellStyleDefault" id="xKf-5i-9cT">
+                                        <rect key="frame" x="0.0" y="88" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xKf-5i-9cT" id="0Fm-qD-hZk">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="CircleChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Bn9-8g-5UP">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="circleChart" id="WSA-oe-ed1"/>
+                                        </connections>
+                                    </tableViewCell>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="N5A-vO-fq4" style="IBUITableViewCellStyleDefault" id="1Ha-E5-to7">
+                                        <rect key="frame" x="0.0" y="132" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1Ha-E5-to7" id="3YW-gb-VCd">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="PieChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="N5A-vO-fq4">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="pieChart" id="pvQ-oy-a9a"/>
+                                        </connections>
+                                    </tableViewCell>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" indentationLevel="1" indentationWidth="0.0" textLabel="YOU-SK-mQU" style="IBUITableViewCellStyleDefault" id="JJR-oU-C7n">
+                                        <rect key="frame" x="0.0" y="176" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JJR-oU-C7n" id="iJk-3W-tcy">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ScatterChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="YOU-SK-mQU">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="scatterChart" id="V7s-JV-4Nx"/>
+                                        </connections>
+                                    </tableViewCell>
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="Sjk-AS-XhW" style="IBUITableViewCellStyleDefault" id="bev-fA-J4Q">
+                                        <rect key="frame" x="0.0" y="220" width="375" height="44"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bev-fA-J4Q" id="nSV-Wu-TAu">
+                                            <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <subviews>
+                                                <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="RadarChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Sjk-AS-XhW">
+                                                    <rect key="frame" x="15" y="0.0" width="325" height="43"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="18"/>
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </tableViewCellContentView>
+                                        <connections>
+                                            <segue destination="Tha-Wr-sPW" kind="push" identifier="radarChart" id="4D9-t3-nzn"/>
+                                        </connections>
+                                    </tableViewCell>
+                                </cells>
+                            </tableViewSection>
+                        </sections>
+                    </tableView>
+                    <navigationItem key="navigationItem" title="PNChart" id="wPu-Ht-gOr"/>
+                </tableViewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="JMX-8U-h8G" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="50" y="31"/>
+        </scene>
+        <!--Navigation Controller-->
+        <scene sceneID="adz-gG-u3z">
+            <objects>
+                <navigationController definesPresentationContext="YES" id="9Rt-UT-IxH" sceneMemberID="viewController">
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="Vgs-8d-rE2">
+                        <rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <connections>
+                        <segue destination="cc5-BF-Ga2" kind="relationship" relationship="rootViewController" id="Jdg-FU-XfU"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="RN0-OP-dIr" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-318" y="31"/>
+        </scene>
+    </scenes>
+    <simulatedMetricsContainer key="defaultSimulatedMetrics">
+        <simulatedStatusBarMetrics key="statusBar"/>
+        <simulatedOrientationMetrics key="orientation"/>
+        <simulatedScreenMetrics key="destination" type="retina4_7.fullscreen"/>
+    </simulatedMetricsContainer>
+    <inferredMetricsTieBreakers>
+        <segue reference="pvQ-oy-a9a"/>
+    </inferredMetricsTieBreakers>
+</document>
diff --git a/camerademo/camerademo/Info.plist b/PNChartdemo/PNChartdemo/Info.plist
similarity index 100%
rename from camerademo/camerademo/Info.plist
rename to PNChartdemo/PNChartdemo/Info.plist
diff --git a/PNChartdemo/PNChartdemo/PCChartViewController.h b/PNChartdemo/PNChartdemo/PCChartViewController.h
new file mode 100755
index 0000000..d8954b3
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PCChartViewController.h
@@ -0,0 +1,38 @@
+//
+//  PCChartViewController.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNChartDelegate.h"
+#import "PNChart.h"
+
+@interface PCChartViewController : UIViewController<PNChartDelegate>
+
+@property (nonatomic) PNLineChart * lineChart;
+@property (nonatomic) PNBarChart * barChart;
+@property (nonatomic) PNCircleChart * circleChart;
+@property (nonatomic) PNPieChart *pieChart;
+@property (nonatomic) PNScatterChart *scatterChart;
+@property (nonatomic) PNRadarChart *radarChart;
+@property (weak, nonatomic) IBOutlet UILabel *centerSwitchLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
+
+- (IBAction)changeValue:(id)sender;
+@property (weak, nonatomic) IBOutlet UIButton *changeValueButton;
+
+@property (weak, nonatomic) IBOutlet UISwitch *animationsSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *leftSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *centerSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *rightSwitch;
+@property (weak, nonatomic) IBOutlet UILabel *leftLabel;
+@property (weak, nonatomic) IBOutlet UILabel *rightLabel;
+
+- (IBAction)rightSwitchChanged:(id)sender;
+- (IBAction)leftSwitchChanged:(id)sender;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PCChartViewController.m b/PNChartdemo/PNChartdemo/PCChartViewController.m
new file mode 100755
index 0000000..ba59f98
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PCChartViewController.m
@@ -0,0 +1,490 @@
+//
+//  PCChartViewController.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PCChartViewController.h"
+
+#define ARC4RANDOM_MAX 0x100000000
+
+@implementation PCChartViewController
+
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    self.titleLabel.textColor = PNFreshGreen;
+    self.leftSwitch.hidden = YES;
+    self.rightSwitch.hidden = YES;
+    self.leftLabel.hidden = YES;
+    self.rightLabel.hidden = YES;
+    self.centerSwitch.hidden = YES;
+    self.centerSwitchLabel.hidden = YES;
+
+    self.changeValueButton.hidden = YES;
+
+    if ([self.title isEqualToString:@"Line Chart"])
+    {
+
+        self.titleLabel.text = @"Line Chart";
+
+        self.rightSwitch.hidden = NO;
+        self.rightLabel.hidden = NO;
+        self.leftSwitch.hidden = NO;
+        self.leftLabel.hidden = NO;
+        self.animationsSwitch.hidden = NO;
+
+        self.leftLabel.text = @"Dark Background";
+        self.rightLabel.text = @"Show Curved Lines";
+
+        self.animationsSwitch.enabled = YES;
+        self.rightSwitch.enabled = YES;
+        self.leftSwitch.enabled = YES;
+        [self.animationsSwitch setOn:NO];
+        [self.rightSwitch setOn:NO];
+        [self.leftSwitch setOn:NO];
+
+
+        self.lineChart.backgroundColor = [UIColor whiteColor];
+        self.lineChart.yGridLinesColor = [UIColor grayColor];
+        [self.lineChart.chartData enumerateObjectsUsingBlock:^(PNLineChartData *obj, NSUInteger idx, BOOL *stop) {
+            obj.pointLabelColor = [UIColor blackColor];
+        }];
+
+        self.lineChart = [[PNLineChart alloc] initWithFrame:CGRectMake(0, 135.0, SCREEN_WIDTH, 200.0)];
+        self.lineChart.showCoordinateAxis = YES;  // ���������������������
+        self.lineChart.yLabelFormat = @"%1.1f"; //���Y���������float���������������������
+        self.lineChart.xLabelFont = [UIFont fontWithName:@"Helvetica-Light" size:8.0];
+        [self.lineChart setXLabels:@[@"SEP 1", @"SEP 2", @"SEP 3", @"SEP 4", @"SEP 5", @"SEP 6", @"SEP 7"]];
+        self.lineChart.yLabelColor = [UIColor blackColor];
+        self.lineChart.xLabelColor = [UIColor blackColor];
+
+        // added an example to show how yGridLines can be enabled
+        // the color is set to clearColor so that the demo remains the same
+        self.lineChart.showGenYLabels = NO;
+        self.lineChart.showYGridLines = YES;
+
+        //Use yFixedValueMax and yFixedValueMin to Fix the Max and Min Y Value
+        //Only if you needed
+        self.lineChart.yFixedValueMax = 300.0;
+        self.lineChart.yFixedValueMin = 0.0;
+
+        self.lineChart.showSmoothLines = YES;
+        
+        [self.lineChart setYLabels:@[
+                @"0",
+                @"50",
+                @"100",
+                @"150",
+                @"200",
+                @"250",
+                @"300",
+        ]
+        ];
+
+//        // Line Chart #1
+//        NSArray *data01Array = @[@15.1, @60.1, @110.4, @10.0, @186.2, @197.2, @276.2];
+//        data01Array = [[data01Array reverseObjectEnumerator] allObjects];
+//        PNLineChartData *data01 = [PNLineChartData new];
+//
+//        data01.rangeColors = @[
+//                [[PNLineChartColorRange alloc] initWithRange:NSMakeRange(10, 30) color:[UIColor redColor]],
+//                [[PNLineChartColorRange alloc] initWithRange:NSMakeRange(100, 200) color:[UIColor purpleColor]]
+//        ];
+//        data01.dataTitle = @"Alpha";
+//        data01.color = PNFreshGreen;
+//        data01.pointLabelColor = [UIColor blackColor];
+//        data01.alpha = 0.3f;
+//        data01.showPointLabel = YES;
+//        data01.pointLabelFont = [UIFont fontWithName:@"Helvetica-Light" size:9.0];
+//        data01.itemCount = data01Array.count;
+//        data01.inflexionPointColor = PNRed;
+//        data01.inflexionPointStyle = PNLineChartPointStyleTriangle;
+//        data01.getData = ^(NSUInteger index) {
+//            CGFloat yValue = [data01Array[index] floatValue];
+//            return [PNLineChartDataItem dataItemWithY:yValue];
+//        };
+
+        // Line Chart #2
+        NSArray *data02Array = @[@0.0, @180.1, @26.4, @202.2, @126.2, @167.2, @276.2];
+        PNLineChartData *data02 = [PNLineChartData new];
+        data02.dataTitle = @"Beta";
+        data02.pointLabelColor = [UIColor blackColor];
+        data02.color = PNTwitterColor;
+        data02.alpha = 0.5f;
+        data02.itemCount = data02Array.count;
+        data02.inflexionPointStyle = PNLineChartPointStyleCircle;
+        data02.getData = ^(NSUInteger index)
+        {
+            CGFloat yValue = [data02Array[index] floatValue];
+            return [PNLineChartDataItem dataItemWithY:yValue];
+        };
+
+        //self.lineChart.chartData = @[data01, data02];
+        self.lineChart.chartData = @[data02];
+        [self.lineChart.chartData enumerateObjectsUsingBlock:^(PNLineChartData *obj, NSUInteger idx, BOOL *stop)
+        {
+            obj.pointLabelColor = [UIColor blackColor];
+        }];
+
+
+        [self.lineChart strokeChart];
+        self.lineChart.delegate = self;
+
+
+        [self.view addSubview:self.lineChart];
+
+        self.lineChart.legendStyle = PNLegendItemStyleStacked;
+        self.lineChart.legendFont = [UIFont boldSystemFontOfSize:12.0f];
+        self.lineChart.legendFontColor = [UIColor redColor];
+
+        UIView *legend = [self.lineChart getLegendWithMaxWidth:320];
+        [legend setFrame:CGRectMake(30, 340, legend.frame.size.width, legend.frame.size.width)];
+        [self.view addSubview:legend];
+    }
+    else if ([self.title isEqualToString:@"Bar Chart"])
+    {
+        static NSNumberFormatter *barChartFormatter;
+        if (!barChartFormatter) {
+            barChartFormatter = [[NSNumberFormatter alloc] init];
+            barChartFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
+            barChartFormatter.allowsFloats = NO;
+            barChartFormatter.maximumFractionDigits = 0;
+        }
+        self.titleLabel.text = @"Bar Chart";
+
+        self.barChart = [[PNBarChart alloc] initWithFrame:CGRectMake(0, 135.0, SCREEN_WIDTH, 200.0)];
+//        self.barChart.showLabel = NO;
+        self.barChart.yLabelFormatter = ^(CGFloat yValue) {
+            return [barChartFormatter stringFromNumber:@(yValue)];
+        };
+
+        self.barChart.yChartLabelWidth = 20.0;
+        self.barChart.chartMarginLeft = 30.0;
+        self.barChart.chartMarginRight = 10.0;
+        self.barChart.chartMarginTop = 5.0;
+        self.barChart.chartMarginBottom = 10.0;
+
+
+        self.barChart.labelMarginTop = 5.0;
+        self.barChart.showChartBorder = YES;
+        [self.barChart setXLabels:@[@"2", @"3", @"4", @"5", @"2", @"3", @"4", @"5"]];
+//       self.barChart.yLabels = @[@-10,@0,@10];
+//        [self.barChart setYValues:@[@10000.0,@30000.0,@10000.0,@100000.0,@500000.0,@1000000.0,@1150000.0,@2150000.0]];
+        [self.barChart setYValues:@[@10.82, @1.88, @6.96, @33.93, @10.82, @1.88, @6.96, @33.93]];
+        [self.barChart setStrokeColors:@[PNGreen, PNGreen, PNRed, PNGreen, PNGreen, PNGreen, PNRed, PNGreen]];
+        self.barChart.isGradientShow = NO;
+        self.barChart.isShowNumbers = NO;
+
+        [self.barChart strokeChart];
+
+        self.barChart.delegate = self;
+
+        [self.view addSubview:self.barChart];
+    } else if ([self.title isEqualToString:@"Circle Chart"]) {
+        self.titleLabel.text = @"Circle Chart";
+
+
+        self.circleChart = [[PNCircleChart alloc] initWithFrame:CGRectMake(0, 150.0, SCREEN_WIDTH, 100.0)
+                                                          total:@100
+                                                        current:@60
+                                                      clockwise:YES];
+
+        self.circleChart.backgroundColor = [UIColor whiteColor];
+
+        [self.circleChart setStrokeColor:[UIColor clearColor]];
+        [self.circleChart setStrokeColorGradientStart:[UIColor blueColor]];
+        [self.circleChart strokeChart];
+
+        [self.view addSubview:self.circleChart];
+    } else if ([self.title isEqualToString:@"Pie Chart"]) {
+        self.titleLabel.text = @"Pie Chart";
+        self.leftSwitch.hidden = NO;
+        self.rightSwitch.hidden = NO;
+        self.leftLabel.hidden = NO;
+        self.rightLabel.hidden = NO;
+        self.centerSwitch.hidden = NO;
+        self.centerSwitchLabel.hidden = NO;
+
+
+        NSArray *items = @[[PNPieChartDataItem dataItemWithValue:10 color:PNLightGreen],
+                [PNPieChartDataItem dataItemWithValue:20 color:PNFreshGreen description:@"WWDC"],
+                [PNPieChartDataItem dataItemWithValue:40 color:PNDeepGreen description:@"GOOG I/O"],
+        ];
+
+        self.pieChart = [[PNPieChart alloc] initWithFrame:CGRectMake((CGFloat) (SCREEN_WIDTH / 2.0 - 100), 135, 200.0, 200.0) items:items];
+        self.pieChart.descriptionTextColor = [UIColor whiteColor];
+        self.pieChart.descriptionTextFont = [UIFont fontWithName:@"Avenir-Medium" size:11.0];
+        self.pieChart.descriptionTextShadowColor = [UIColor clearColor];
+        self.pieChart.showAbsoluteValues = NO;
+        self.pieChart.showOnlyValues = NO;
+        [self.pieChart strokeChart];
+
+
+        self.pieChart.legendStyle = PNLegendItemStyleStacked;
+        self.pieChart.legendFont = [UIFont boldSystemFontOfSize:12.0f];
+
+        UIView *legend = [self.pieChart getLegendWithMaxWidth:200];
+        [legend setFrame:CGRectMake(130, 350, legend.frame.size.width, legend.frame.size.height)];
+        [self.view addSubview:legend];
+
+        [self.view addSubview:self.pieChart];
+        self.changeValueButton.hidden = YES;
+    } else if ([self.title isEqualToString:@"Scatter Chart"]) {
+        self.animationsSwitch.hidden = YES;
+
+        self.titleLabel.text = @"Scatter Chart";
+
+        self.scatterChart = [[PNScatterChart alloc] initWithFrame:CGRectMake((CGFloat) (SCREEN_WIDTH / 6.0 - 30), 135, 280, 200)];
+//        self.scatterChart.yLabelFormat = @"xxx %1.1f";
+        [self.scatterChart setAxisXWithMinimumValue:20 andMaxValue:100 toTicks:6];
+        [self.scatterChart setAxisYWithMinimumValue:30 andMaxValue:50 toTicks:5];
+        [self.scatterChart setAxisXLabel:@[@"x1", @"x2", @"x3", @"x4", @"x5", @"x6"]];
+        [self.scatterChart setAxisYLabel:@[@"y1", @"y2", @"y3", @"y4", @"y5"]];
+
+        NSArray *data01Array = [self randomSetOfObjects];
+        PNScatterChartData *data01 = [PNScatterChartData new];
+        data01.strokeColor = PNGreen;
+        data01.fillColor = PNFreshGreen;
+        data01.size = 2;
+        data01.itemCount = [data01Array[0] count];
+        data01.inflexionPointStyle = PNScatterChartPointStyleCircle;
+        __block NSMutableArray *XAr1 = [NSMutableArray arrayWithArray:data01Array[0]];
+        __block NSMutableArray *YAr1 = [NSMutableArray arrayWithArray:data01Array[1]];
+
+        data01.getData = ^(NSUInteger index) {
+            CGFloat xValue;
+            xValue = [XAr1[index] floatValue];
+            CGFloat yValue = [YAr1[index] floatValue];
+            return [PNScatterChartDataItem dataItemWithX:xValue AndWithY:yValue];
+        };
+
+        [self.scatterChart setup];
+        self.scatterChart.chartData = @[data01];
+/***    
+        this is for drawing line to compare
+        CGPoint start = CGPointMake(20, 35);
+        CGPoint end = CGPointMake(80, 45);
+        [self.scatterChart drawLineFromPoint:start ToPoint:end WithLineWith:2 AndWithColor:PNBlack];
+***/
+        self.scatterChart.delegate = self;
+        self.changeValueButton.hidden = YES;
+        [self.view addSubview:self.scatterChart];
+    } else if ([self.title isEqualToString:@"Radar Chart"]) {
+        self.titleLabel.text = @"Radar Chart";
+
+        self.leftSwitch.hidden = NO;
+        self.rightSwitch.hidden = NO;
+        self.leftLabel.hidden = NO;
+        self.rightLabel.hidden = NO;
+        self.leftLabel.text = @"Labels Style";
+        self.rightLabel.text = @"Graduation";
+
+
+        NSArray *items = @[[PNRadarChartDataItem dataItemWithValue:3 description:@"Art"],
+                [PNRadarChartDataItem dataItemWithValue:2 description:@"Math"],
+                [PNRadarChartDataItem dataItemWithValue:8 description:@"Sports"],
+                [PNRadarChartDataItem dataItemWithValue:5 description:@"Literature"],
+                [PNRadarChartDataItem dataItemWithValue:4 description:@"Other"],
+        ];
+        self.radarChart = [[PNRadarChart alloc] initWithFrame:CGRectMake(0, 135.0, SCREEN_WIDTH, 300.0) items:items valueDivider:1];
+
+        self.radarChart.plotColor = [UIColor redColor];
+
+        [self.radarChart strokeChart];
+
+        [self.view addSubview:self.radarChart];
+    }
+
+}
+
+
+- (void)userClickedOnLineKeyPoint:(CGPoint)point lineIndex:(NSInteger)lineIndex pointIndex:(NSInteger)pointIndex {
+    NSLog(@"Click Key on line %f, %f line index is %d and point index is %d", point.x, point.y, (int) lineIndex, (int) pointIndex);
+}
+
+- (void)userClickedOnLinePoint:(CGPoint)point lineIndex:(NSInteger)lineIndex {
+    NSLog(@"Click on line %f, %f, line index is %d", point.x, point.y, (int) lineIndex);
+}
+
+
+- (IBAction)changeValue:(id)sender {
+
+    if ([self.title isEqualToString:@"Line Chart"]) {
+
+        // Line Chart #1
+        NSArray *data01Array = @[@(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300)];
+        PNLineChartData *data01 = [PNLineChartData new];
+        data01.color = PNFreshGreen;
+        data01.itemCount = data01Array.count;
+        data01.inflexionPointColor = PNRed;
+        data01.inflexionPointStyle = PNLineChartPointStyleTriangle;
+        data01.getData = ^(NSUInteger index) {
+            CGFloat yValue = [data01Array[index] floatValue];
+            return [PNLineChartDataItem dataItemWithY:yValue];
+        };
+
+        // Line Chart #2
+        NSArray *data02Array = @[@(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300), @(arc4random() % 300)];
+        PNLineChartData *data02 = [PNLineChartData new];
+        data02.color = PNTwitterColor;
+        data02.itemCount = data02Array.count;
+        data02.inflexionPointStyle = PNLineChartPointStyleSquare;
+        data02.getData = ^(NSUInteger index) {
+            CGFloat yValue = [data02Array[index] floatValue];
+            return [PNLineChartDataItem dataItemWithY:yValue];
+        };
+
+        [self.lineChart setXLabels:@[@"DEC 1", @"DEC 2", @"DEC 3", @"DEC 4", @"DEC 5", @"DEC 6", @"DEC 7"]];
+        [self.lineChart updateChartData:@[data01, data02]];
+
+    } else if ([self.title isEqualToString:@"Bar Chart"]) {
+        [self.barChart setXLabels:@[@"Jan 1", @"Jan 2", @"Jan 3", @"Jan 4", @"Jan 5", @"Jan 6", @"Jan 7"]];
+        [self.barChart updateChartData:@[@(arc4random() % 30), @(arc4random() % 30), @(arc4random() % 30), @(arc4random() % 30), @(arc4random() % 30), @(arc4random() % 30), @(arc4random() % 30)]];
+    } else if ([self.title isEqualToString:@"Circle Chart"]) {
+        [self.circleChart updateChartByCurrent:@(arc4random() % 100)];
+    } else if ([self.title isEqualToString:@"Scatter Chart"]) {
+        // will be code soon.
+    }
+
+}
+
+- (void)userClickedOnBarAtIndex:(NSInteger)barIndex {
+
+    NSLog(@"Click on bar %@", @(barIndex));
+
+    PNBar *bar = self.barChart.bars[(NSUInteger) barIndex];
+
+    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+
+    animation.fromValue = @1.0;
+    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+    animation.toValue = @1.1;
+    animation.duration = 0.2;
+    animation.repeatCount = 0;
+    animation.autoreverses = YES;
+    animation.removedOnCompletion = YES;
+    animation.fillMode = kCAFillModeForwards;
+
+    [bar.layer addAnimation:animation forKey:@"Float"];
+}
+
+/* this function is used only for creating random points */
+- (NSArray *)randomSetOfObjects {
+    NSMutableArray *array = [NSMutableArray array];
+    NSString *LabelFormat = @"%1.f";
+    NSMutableArray *XAr = [NSMutableArray array];
+    NSMutableArray *YAr = [NSMutableArray array];
+    for (int i = 0; i < 25; i++) {
+        [XAr addObject:[NSString stringWithFormat:LabelFormat, (((double) arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisX_maxValue - self.scatterChart.AxisX_minValue) + self.scatterChart.AxisX_minValue)]];
+        [YAr addObject:[NSString stringWithFormat:LabelFormat, (((double) arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisY_maxValue - self.scatterChart.AxisY_minValue) + self.scatterChart.AxisY_minValue)]];
+    }
+    [array addObject:XAr];
+    [array addObject:YAr];
+    return array;
+}
+
+- (IBAction)rightSwitchChanged:(id)sender
+{
+    if ([self.title isEqualToString:@"Pie Chart"]) {
+        UISwitch *showLabels = (UISwitch *) sender;
+        self.pieChart.showOnlyValues = !showLabels.on;
+        [self.pieChart strokeChart];
+    }
+    if ([self.title isEqualToString:@"Radar Chart"]) {
+        UISwitch *showLabels = (UISwitch *) sender;
+        self.radarChart.isShowGraduation = !showLabels.on;
+        [self.radarChart strokeChart];
+    } else if ([self.title isEqualToString:@"Line Chart"])
+    {
+        UISwitch *showLabels = (UISwitch *) sender;
+        self.lineChart.showSmoothLines = showLabels.on;
+        NSLog(@"self.lineChart.showSmoothLines : %d", self.lineChart.showSmoothLines);
+        [self.lineChart strokeChart];
+    }
+}
+
+- (IBAction)centerSwitchChanged:(id)sender {
+    if (self.pieChart) {
+        [self.pieChart setEnableMultipleSelection:self.centerSwitch.on];
+        [self.pieChart strokeChart];
+    }
+
+}
+
+- (IBAction)leftSwitchChanged:(id)sender {
+    if ([self.title isEqualToString:@"Pie Chart"]) {
+        UISwitch *showRelative = (UISwitch *) sender;
+        self.pieChart.showAbsoluteValues = !showRelative.on;
+        [self.pieChart strokeChart];
+    } else if ([self.title isEqualToString:@"Radar Chart"]) {
+        UISwitch *showRelative = (UISwitch *) sender;
+        if (showRelative.on) {
+            self.radarChart.labelStyle = PNRadarChartLabelStyleHorizontal;
+        } else {
+            self.radarChart.labelStyle = PNRadarChartLabelStyleCircle;
+        }
+        [self.radarChart strokeChart];
+
+    } else if ([self.title isEqualToString:@"Line Chart"]) {
+        UISwitch *senderSwitch = (UISwitch *) sender;
+        if (senderSwitch.isOn) {
+            UIColor *lineChartLabelColor = [UIColor cyanColor];
+            UIColor *darkBackgroundColor = [UIColor colorWithRed:0.47 green:0.47 blue:0.47 alpha:1.0];
+
+            UIColor *gridLinesForDarkBackgroundColor = [UIColor colorWithRed:242 / 255.0 green:242 / 255.0 blue:242 / 255.0 alpha:1.0];
+            self.lineChart.backgroundColor = darkBackgroundColor;
+            self.lineChart.yGridLinesColor = gridLinesForDarkBackgroundColor;
+            self.lineChart.showYGridLines = YES;
+            self.lineChart.yLabelColor = lineChartLabelColor;
+            self.lineChart.xLabelColor = lineChartLabelColor;
+            [self.lineChart.chartData enumerateObjectsUsingBlock:^(PNLineChartData *obj, NSUInteger idx, BOOL *stop) {
+                obj.pointLabelColor = lineChartLabelColor;
+            }];
+        } else {
+            self.lineChart.backgroundColor = [UIColor whiteColor];
+            self.lineChart.yGridLinesColor = [UIColor grayColor];
+            self.lineChart.yLabelColor = [UIColor blackColor];
+            self.lineChart.xLabelColor = [UIColor blackColor];
+            [self.lineChart.chartData enumerateObjectsUsingBlock:^(PNLineChartData *obj, NSUInteger idx, BOOL *stop) {
+                obj.pointLabelColor = [UIColor blackColor];
+            }];
+        }
+        [self.lineChart setXLabels:@[@"DEC 1", @"DEC 2", @"DEC 3", @"DEC 4", @"DEC 5", @"DEC 6", @"DEC 7"]];
+        [self.lineChart setYLabels:@[
+                @"0 min",
+                @"50 min",
+                @"100 min",
+                @"150 min",
+                @"200 min",
+                @"250 min",
+                @"300 min",
+        ]
+        ];
+        [self.lineChart strokeChart];
+    }
+}
+
+- (IBAction)animationsSwitchChanged:(UISwitch *)sender {
+    if ([self.title isEqualToString:@"Circle Chart"]) {
+        self.circleChart.displayAnimated = sender.on;
+        [self.circleChart strokeChart];
+    } else if ([self.title isEqualToString:@"Line Chart"]) {
+        self.lineChart.displayAnimated = sender.on;
+        [self.lineChart strokeChart];
+    } else if ([self.title isEqualToString:@"Bar Chart"]) {
+        self.barChart.displayAnimated = sender.on;
+        [self.barChart strokeChart];
+    } else if ([self.title isEqualToString:@"Pie Chart"]) {
+        self.pieChart.displayAnimated = sender.on;
+        [self.pieChart strokeChart];
+    } else if ([self.title isEqualToString:@"Radar Chart"]) {
+        self.radarChart.displayAnimated = sender.on;
+        [self.radarChart strokeChart];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PCChartsTableViewController.h b/PNChartdemo/PNChartdemo/PCChartsTableViewController.h
new file mode 100755
index 0000000..bc25f8e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PCChartsTableViewController.h
@@ -0,0 +1,13 @@
+//
+//  PCChartsTableViewController.h
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-12-1.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface PCChartsTableViewController : UITableViewController
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PCChartsTableViewController.m b/PNChartdemo/PNChartdemo/PCChartsTableViewController.m
new file mode 100755
index 0000000..39d923e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PCChartsTableViewController.m
@@ -0,0 +1,56 @@
+//
+//  PCChartsTableViewController.m
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-12-1.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PCChartsTableViewController.h"
+
+@implementation PCChartsTableViewController
+
+// In a story board-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
+{
+    // Get the new view controller using [segue destinationViewController].
+    // Pass the selected object to the new view controller.
+
+    UIViewController * viewController = [segue destinationViewController];
+
+    if ([segue.identifier isEqualToString:@"lineChart"]) {
+
+        //Add line chart
+
+        viewController.title = @"Line Chart";
+
+    } else if ([segue.identifier isEqualToString:@"barChart"])
+    {
+        //Add bar chart
+
+        viewController.title = @"Bar Chart";
+    } else if ([segue.identifier isEqualToString:@"circleChart"])
+    {
+        //Add circle chart
+
+        viewController.title = @"Circle Chart";
+
+    } else if ([segue.identifier isEqualToString:@"pieChart"])
+    {
+        //Add pie chart
+
+        viewController.title = @"Pie Chart";
+    } else if ([segue.identifier isEqualToString:@"scatterChart"])
+    {
+        //Add scatter chart
+        
+        viewController.title = @"Scatter Chart";
+    }else if ([segue.identifier isEqualToString:@"radarChart"])
+    {
+        //Add radar chart
+        
+        viewController.title = @"Radar Chart";
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNBar.h b/PNChartdemo/PNChartdemo/PNChart/PNBar.h
new file mode 100755
index 0000000..68e6b0b
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNBar.h
@@ -0,0 +1,37 @@
+//
+//  PNBar.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+
+@interface PNBar : UIView
+
+
+- (void)rollBack;
+
+@property (nonatomic) float grade;
+@property (nonatomic) float maxDivisor;
+
+@property (nonatomic) CAShapeLayer *chartLine;
+@property (nonatomic) UIColor *barColor;
+@property (nonatomic) UIColor *barColorGradientStart;
+@property (nonatomic) CGFloat barRadius;
+@property (nonatomic) CAShapeLayer *gradientMask;
+
+@property (nonatomic) CAShapeLayer *gradeLayer;
+@property (nonatomic) CATextLayer* textLayer;
+
+/** Text color for all bars in the chart. */
+@property (nonatomic) UIColor * labelTextColor;
+
+@property (nonatomic, assign) BOOL isNegative;          //!< ���������������
+@property (nonatomic, assign) BOOL isShowNumber;        //!< ������������numbers
+
+/** Display the bar with or without animation. Default is YES. **/
+@property (nonatomic) BOOL displayAnimated;
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNBar.m b/PNChartdemo/PNChartdemo/PNChart/PNBar.m
new file mode 100755
index 0000000..8ea5fc9
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNBar.m
@@ -0,0 +1,288 @@
+//
+//  PNBar.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNBar.h"
+#import "PNColor.h"
+#import <CoreText/CoreText.h>
+
+@interface PNBar ()
+
+@property (nonatomic) float copyGrade;
+
+@end
+
+@implementation PNBar
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        _chartLine              = [CAShapeLayer layer];
+        _chartLine.lineCap      = kCALineCapButt;
+        _chartLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartLine.lineWidth    = self.frame.size.width;
+        _chartLine.strokeEnd    = 0.0;
+        self.clipsToBounds      = YES;
+        [self.layer addSublayer:_chartLine];
+        self.barRadius = 2.0;
+    }
+
+    return self;
+}
+
+-(void)setBarRadius:(CGFloat)barRadius
+{
+    _barRadius = barRadius;
+    self.layer.cornerRadius = _barRadius;
+}
+
+
+- (void)setGrade:(float)grade
+{
+    _copyGrade = grade;
+    CGFloat startPosY = (1 - grade) * self.frame.size.height;
+
+    UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+    [progressline moveToPoint:CGPointMake(self.frame.size.width / 2.0, self.frame.size.height)];
+    [progressline addLineToPoint:CGPointMake(self.frame.size.width / 2.0, startPosY)];
+
+    [progressline setLineWidth:1.0];
+    [progressline setLineCapStyle:kCGLineCapSquare];
+    [self addAnimationIfNeededWithProgressLine:progressline];
+
+
+    if (_barColor) {
+        _chartLine.strokeColor = [_barColor CGColor];
+    }
+    else {
+        _chartLine.strokeColor = [PNGreen CGColor];
+    }
+
+    if (_grade) {
+        
+        _chartLine.path = progressline.CGPath;
+        
+        if (_barColorGradientStart) {
+            
+            // Add gradient
+            self.gradientMask.path = progressline.CGPath;
+  
+            CABasicAnimation* opacityAnimation = [self fadeAnimation];
+            [self.textLayer addAnimation:opacityAnimation forKey:nil];
+
+        }
+        
+    }else{
+        _chartLine.strokeEnd = 1.0;
+        
+        _chartLine.path = progressline.CGPath;
+        // Check if user wants to add a gradient from the start color to the bar color
+        if (_barColorGradientStart) {
+            
+            // Add gradient
+            self.gradientMask = [CAShapeLayer layer];
+            self.gradientMask.fillColor = [[UIColor clearColor] CGColor];
+            self.gradientMask.strokeColor = [[UIColor blackColor] CGColor];
+            self.gradientMask.lineWidth    = self.frame.size.width;
+            self.gradientMask.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
+            self.gradientMask.path = progressline.CGPath;
+            
+            CAGradientLayer *gradientLayer = [CAGradientLayer layer];
+            gradientLayer.startPoint = CGPointMake(0.0,0.0);
+            gradientLayer.endPoint = CGPointMake(1.0 ,0.0);
+            gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
+            UIColor *middleColor = [UIColor colorWithWhite:255/255 alpha:0.8];
+            NSArray *colors = @[
+                                (__bridge id)self.barColor.CGColor,
+                                (__bridge id)middleColor.CGColor,
+                                (__bridge id)self.barColor.CGColor
+                                ];
+            gradientLayer.colors = colors;
+            
+            [gradientLayer setMask:self.gradientMask];
+            
+            [_chartLine addSublayer:gradientLayer];
+            
+            self.gradientMask.strokeEnd = 1.0;
+
+            CABasicAnimation* opacityAnimation = [self fadeAnimation];
+            [self.textLayer addAnimation:opacityAnimation forKey:nil];
+        }
+    }
+    
+    _grade = grade;
+
+}
+
+
+- (void)rollBack
+{
+    [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations: ^{
+        _chartLine.strokeColor = [UIColor clearColor].CGColor;
+    } completion:nil];
+}
+
+- (void)setBarColorGradientStart:(UIColor *)barColorGradientStart
+{
+    // Set gradient color, remove any existing sublayer first
+    for (CALayer *sublayer in [_chartLine sublayers]) {
+        [sublayer removeFromSuperlayer];
+    }
+    _barColorGradientStart = barColorGradientStart;
+
+    [self setGrade:_grade];
+
+}
+
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect
+{
+    CGContextRef context = UIGraphicsGetCurrentContext();
+
+    CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
+    CGContextFillRect(context, rect);
+}
+
+
+// add number display on the top of bar
+-(CGPathRef)gradePath:(CGRect)rect
+{
+    return nil;
+}
+
+-(CATextLayer*)textLayer
+{
+    if (!_textLayer) {
+        _textLayer = [[CATextLayer alloc]init];
+        [_textLayer setString:@"0"];
+        [_textLayer setAlignmentMode:kCAAlignmentCenter];
+        [_textLayer setForegroundColor:[_labelTextColor CGColor]];
+       _textLayer.hidden = YES;
+
+    }
+
+    return _textLayer;
+}
+
+- (void) setLabelTextColor:(UIColor *)labelTextColor {
+    _labelTextColor = labelTextColor;
+    [_textLayer setForegroundColor:[_labelTextColor CGColor]];
+}
+
+-(void)setGradeFrame:(CGFloat)grade startPosY:(CGFloat)startPosY
+{
+    CGFloat textheigt = self.bounds.size.height*self.grade;
+  
+    CGFloat topSpace = self.bounds.size.height * (1-self.grade);
+    CGFloat textWidth = self.bounds.size.width;
+  
+    [_chartLine addSublayer:self.textLayer];
+    [self.textLayer setFontSize:18.0];
+  
+    [self.textLayer setString:[[NSString alloc]initWithFormat:@"%0.f",grade*self.maxDivisor]];
+  
+    CGSize size = CGSizeMake(320,2000); //������������������������
+    NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]};
+    size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
+    float verticalY ;
+  
+    if (size.height>=textheigt) {
+      
+      verticalY = topSpace - size.height;
+    } else {
+      verticalY = topSpace +  (textheigt-size.height)/2.0;
+    }
+  
+    [self.textLayer setFrame:CGRectMake((textWidth-size.width)/2.0,verticalY, size.width,size.height)];
+    self.textLayer.contentsScale = [UIScreen mainScreen].scale;
+
+}
+
+- (void)setIsShowNumber:(BOOL)isShowNumber{
+  if (isShowNumber) {
+    self.textLayer.hidden = NO;
+    [self setGradeFrame:_copyGrade startPosY:0];
+  }else{
+    self.textLayer.hidden = YES;
+  }
+}
+- (void)setIsNegative:(BOOL)isNegative{
+  if (isNegative) {
+    [self.textLayer setString:[[NSString alloc]initWithFormat:@"- %1.f",_grade*self.maxDivisor]];
+    
+    CGSize size = CGSizeMake(320,2000); //������������������������
+    NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]};
+    size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
+    CGRect frame = self.textLayer.frame;
+    frame.origin.x = (self.bounds.size.width - size.width)/2.0;
+    frame.size = size;
+    self.textLayer.frame = frame;
+      
+    [self addRotationAnimationIfNeeded];
+  }
+}
+
+-(CABasicAnimation*)fadeAnimation
+{
+    CABasicAnimation* fadeAnimation = nil;
+    if (self.displayAnimated) {
+        fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeAnimation.fromValue = [NSNumber numberWithFloat:0.0];
+        fadeAnimation.toValue = [NSNumber numberWithFloat:1.0];
+        fadeAnimation.duration = 2.0;
+    }
+    return fadeAnimation;
+}
+
+-(void)addAnimationIfNeededWithProgressLine:(UIBezierPath *)progressline
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = nil;
+        
+        if (_grade) {
+            pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+            pathAnimation.fromValue = (id)_chartLine.path;
+            pathAnimation.toValue = (id)[progressline CGPath];
+            pathAnimation.duration = 0.5f;
+            pathAnimation.autoreverses = NO;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            [_chartLine addAnimation:pathAnimation forKey:@"animationKey"];
+        }
+        else {
+            pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+            pathAnimation.duration = 1.0;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            pathAnimation.fromValue = @0.0f;
+            pathAnimation.toValue = @1.0f;
+            [_chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+        
+        [self.gradientMask addAnimation:pathAnimation forKey:@"animationKey"];
+    }
+}
+
+- (void)addRotationAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation* rotationAnimation;
+        rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+        rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI];
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        rotationAnimation.duration = 0.1;
+        rotationAnimation.repeatCount = 0;//������������������������������������
+        rotationAnimation.cumulative = NO;
+        rotationAnimation.removedOnCompletion = NO;
+        rotationAnimation.fillMode = kCAFillModeForwards;
+        [self.textLayer addAnimation:rotationAnimation forKey:@"Rotation"];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNBarChart.h b/PNChartdemo/PNChartdemo/PNChart/PNBarChart.h
new file mode 100755
index 0000000..e628c08
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNBarChart.h
@@ -0,0 +1,123 @@
+//
+//  PNBarChart.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNGenericChart.h"
+#import "PNChartDelegate.h"
+#import "PNBar.h"
+
+#define kXLabelMargin 15
+#define kYLabelMargin 15
+#define kYLabelHeight 11
+#define kXLabelHeight 20
+
+typedef NSString *(^PNYLabelFormatter)(CGFloat yLabelValue);
+
+@interface PNBarChart : PNGenericChart
+
+/**
+ * Draws the chart in an animated fashion.
+ */
+- (void)strokeChart;
+
+@property (nonatomic) NSArray *xLabels;
+@property (nonatomic) NSArray *yLabels;
+@property (nonatomic) NSArray *yValues;
+
+@property (nonatomic) NSMutableArray * bars;
+
+@property (nonatomic) CGFloat xLabelWidth;
+@property (nonatomic) float yValueMax;
+@property (nonatomic) UIColor *strokeColor;
+@property (nonatomic) NSArray *strokeColors;
+
+
+/** Update Values. */
+- (void)updateChartData:(NSArray *)data;
+
+/** Changes chart margin. */
+@property (nonatomic) CGFloat yChartLabelWidth;
+
+/** Formats the ylabel text. */
+@property (copy) PNYLabelFormatter yLabelFormatter;
+
+/** Prefix to y label values, none if unset. */
+@property (nonatomic) NSString *yLabelPrefix;
+
+/** Suffix to y label values, none if unset. */
+@property (nonatomic) NSString *yLabelSuffix;
+
+@property (nonatomic) CGFloat chartMarginLeft;
+@property (nonatomic) CGFloat chartMarginRight;
+@property (nonatomic) CGFloat chartMarginTop;
+@property (nonatomic) CGFloat chartMarginBottom;
+
+/** Controls whether labels should be displayed. */
+@property (nonatomic) BOOL showLabel;
+
+/** Controls whether the chart border line should be displayed. */
+@property (nonatomic) BOOL showChartBorder;
+
+@property (nonatomic) UIColor *chartBorderColor;
+
+/** Controls whether the chart Horizontal separator should be displayed. */
+@property (nonatomic, assign) BOOL showLevelLine;
+
+/** Chart bottom border, co-linear with the x-axis. */
+@property (nonatomic) CAShapeLayer * chartBottomLine;
+
+/** Chart bottom border, level separator-linear with the x-axis. */
+@property (nonatomic) CAShapeLayer * chartLevelLine;
+
+/** Chart left border, co-linear with the y-axis. */
+@property (nonatomic) CAShapeLayer * chartLeftLine;
+
+/** Corner radius for all bars in the chart. */
+@property (nonatomic) CGFloat barRadius;
+
+/** Width of all bars in the chart. */
+@property (nonatomic) CGFloat barWidth;
+
+@property (nonatomic) CGFloat labelMarginTop;
+
+/** Background color of all bars in the chart. */
+@property (nonatomic) UIColor * barBackgroundColor;
+
+/** Text color for all bars in the chart. */
+@property (nonatomic) UIColor * labelTextColor;
+
+/** Font for all bars in the chart. */
+@property (nonatomic) UIFont * labelFont;
+
+/** How many labels on the x-axis to skip in between displaying labels. */
+@property (nonatomic) NSInteger xLabelSkip;
+
+/** How many labels on the y-axis to skip in between displaying labels. */
+@property (nonatomic) NSInteger yLabelSum;
+
+/** The maximum for the range of values to display on the y-axis. */
+@property (nonatomic) CGFloat yMaxValue;
+
+/** The minimum for the range of values to display on the y-axis. */
+@property (nonatomic) CGFloat yMinValue;
+
+/** Controls whether each bar should have a gradient fill. */
+@property (nonatomic) UIColor *barColorGradientStart;
+
+/** Controls whether text for x-axis be straight or rotate 45 degree. */
+@property (nonatomic) BOOL rotateForXAxisText;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+/**whether show gradient bar*/
+@property (nonatomic, assign) BOOL isGradientShow;
+
+/** whether show numbers*/
+@property (nonatomic, assign) BOOL isShowNumbers;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNBarChart.m b/PNChartdemo/PNChartdemo/PNChart/PNBarChart.m
new file mode 100755
index 0000000..50e035c
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNBarChart.m
@@ -0,0 +1,459 @@
+//
+//  PNBarChart.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNBarChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+
+@interface PNBarChart () {
+    NSMutableArray *_xChartLabels;
+    NSMutableArray *_yChartLabels;
+}
+
+- (UIColor *)barColorAtIndex:(NSUInteger)index;
+
+@end
+
+@implementation PNBarChart
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    [super setupDefaultValues];
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds   = YES;
+    _showLabel           = YES;
+    _barBackgroundColor  = PNLightGrey;
+    _labelTextColor      = [UIColor grayColor];
+    _labelFont           = [UIFont systemFontOfSize:11.0f];
+    _xChartLabels        = [NSMutableArray array];
+    _yChartLabels        = [NSMutableArray array];
+    _bars                = [NSMutableArray array];
+    _xLabelSkip          = 1;
+    _yLabelSum           = 4;
+    _labelMarginTop      = 2;
+    _chartMarginLeft     = 25.0;
+    _chartMarginRight    = 25.0;
+    _chartMarginTop      = 25.0;
+    _chartMarginBottom   = 25.0;
+    _barRadius           = 2.0;
+    _showChartBorder     = NO;
+    _chartBorderColor    = PNLightGrey;
+    _showLevelLine       = NO;
+    _yChartLabelWidth    = 18;
+    _rotateForXAxisText  = false;
+    _isGradientShow      = YES;
+    _isShowNumbers       = YES;
+    _yLabelPrefix        = @"";
+    _yLabelSuffix        = @"";
+	_yLabelFormatter = ^(CGFloat yValue){
+		return [NSString stringWithFormat:@"%1.f",yValue];
+	};
+}
+
+- (void)setYValues:(NSArray *)yValues
+{
+    _yValues = yValues;
+  //make the _yLabelSum value dependant of the distinct values of yValues to avoid duplicates on yAxis
+
+  if (_showLabel) {
+    [self __addYCoordinateLabelsValues];
+  } else {
+    [self processYMaxValue];
+  }
+}
+
+- (void)processYMaxValue {
+    NSArray *yAxisValues = _yLabels ? _yLabels : _yValues;
+    _yLabelSum = _yLabels ? _yLabels.count - 1 :_yLabelSum;
+    if (_yMaxValue) {
+        _yValueMax = _yMaxValue;
+    } else {
+        [self getYValueMax:yAxisValues];
+    }
+
+    if (_yLabelSum==4) {
+        _yLabelSum = yAxisValues.count;
+        (_yLabelSum % 2 == 0) ? _yLabelSum : _yLabelSum++;
+    }
+}
+
+#pragma mark - Private Method
+#pragma mark - Add Y Label
+- (void)__addYCoordinateLabelsValues{
+
+  [self viewCleanupForCollection:_yChartLabels];
+
+  [self processYMaxValue];
+
+  float sectionHeight = (self.frame.size.height - _chartMarginTop - _chartMarginBottom - kXLabelHeight) / _yLabelSum;
+    
+  for (int i = 0; i <= _yLabelSum; i++) {
+    NSString *labelText;
+    if (_yLabels) {
+      float yAsixValue = [_yLabels[_yLabels.count - i - 1] floatValue];
+      labelText= _yLabelFormatter(yAsixValue);
+    } else {
+      labelText = _yLabelFormatter((float)_yValueMax * ( (_yLabelSum - i) / (float)_yLabelSum ));
+    }
+
+    PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectZero];
+    label.font = _labelFont;
+    label.textColor = _labelTextColor;
+    [label setTextAlignment:NSTextAlignmentRight];
+    label.text = [NSString stringWithFormat:@"%@%@%@", _yLabelPrefix, labelText, _yLabelSuffix];
+    
+    [self addSubview:label];
+      
+    label.frame = (CGRect){0, sectionHeight * i + _chartMarginTop - kYLabelHeight/2.0 + kXLabelHeight + _labelMarginTop, _yChartLabelWidth, kYLabelHeight};
+
+    [_yChartLabels addObject:label];
+  }
+}
+
+-(void)updateChartData:(NSArray *)data{
+    self.yValues = data;
+    [self updateBar];
+}
+
+- (void)getYValueMax:(NSArray *)yLabels
+{
+    CGFloat max = [[yLabels valueForKeyPath:@"@max.floatValue"] floatValue];
+
+    //ensure max is even
+   _yValueMax = max ;
+
+    if (_yValueMax == 0) {
+        _yValueMax = _yMinValue;
+    }
+}
+
+- (void)setXLabels:(NSArray *)xLabels
+{
+    _xLabels = xLabels;
+
+    if (_xChartLabels) {
+        [self viewCleanupForCollection:_xChartLabels];
+    }else{
+        _xChartLabels = [NSMutableArray new];
+    }
+
+	_xLabelWidth = (self.frame.size.width - _chartMarginLeft - _chartMarginRight) / [xLabels count];
+
+    if (_showLabel) {
+        int labelAddCount = 0;
+        for (int index = 0; index < _xLabels.count; index++) {
+            labelAddCount += 1;
+
+            if (labelAddCount == _xLabelSkip) {
+                NSString *labelText = [_xLabels[index] description];
+                PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0, 0, _xLabelWidth, kXLabelHeight)];
+                label.font = _labelFont;
+                label.textColor = _labelTextColor;
+                [label setTextAlignment:NSTextAlignmentCenter];
+                label.text = labelText;
+                //[label sizeToFit];
+                CGFloat labelXPosition;
+                if (_rotateForXAxisText){
+                    label.transform = CGAffineTransformMakeRotation(M_PI / 4);
+                    labelXPosition = (index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /1.5);
+                }
+                else{
+                    labelXPosition = (index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0 );
+                }
+                label.center = CGPointMake(labelXPosition,
+                                           self.frame.size.height - _chartMarginTop + label.frame.size.height /2.0 + _labelMarginTop);
+                labelAddCount = 0;
+
+                [_xChartLabels addObject:label];
+                [self addSubview:label];
+            }
+        }
+    }
+}
+
+
+- (void)setStrokeColor:(UIColor *)strokeColor
+{
+    _strokeColor = strokeColor;
+}
+
+- (void)updateBar
+{
+
+    //Add bars
+    CGFloat chartCavanHeight = self.frame.size.height - _chartMarginTop - _chartMarginBottom - kXLabelHeight;
+    NSInteger index = 0;
+
+    for (NSNumber *valueString in _yValues) {
+
+        PNBar *bar;
+
+        if (_bars.count == _yValues.count) {
+            bar = [_bars objectAtIndex:index];
+        }else{
+            CGFloat barWidth;
+            CGFloat barXPosition;
+
+            if (_barWidth) {
+                barWidth = _barWidth;
+                barXPosition = index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0 - _barWidth /2.0;
+            }else{
+                barXPosition = index *  _xLabelWidth + _chartMarginLeft + _xLabelWidth * 0.25;
+                if (_showLabel) {
+                    barWidth = _xLabelWidth * 0.5;
+
+                }
+                else {
+                    barWidth = _xLabelWidth * 0.6;
+
+                }
+            }
+
+            bar = [[PNBar alloc] initWithFrame:CGRectMake(barXPosition, //Bar X position
+                                                          self.frame.size.height - chartCavanHeight - kXLabelHeight - _chartMarginBottom + _chartMarginTop , //Bar Y position
+                                                          barWidth, // Bar witdh
+                                                          self.showLevelLine ? chartCavanHeight/2.0:chartCavanHeight)]; //Bar height
+
+            //Change Bar Radius
+            bar.barRadius = _barRadius;
+            
+            //Set Bar Animation
+            bar.displayAnimated = self.displayAnimated;
+
+            //Change Bar Background color
+            bar.backgroundColor = _barBackgroundColor;
+            //Bar StrokColor First
+            if (self.strokeColor) {
+                bar.barColor = self.strokeColor;
+            }else{
+                bar.barColor = [self barColorAtIndex:index];
+            }
+            
+            if (self.labelTextColor) {
+                bar.labelTextColor = self.labelTextColor;
+            }
+
+            // Add gradient
+            if (self.isGradientShow) {
+             bar.barColorGradientStart = bar.barColor;
+            }
+
+            //For Click Index
+            bar.tag = index;
+
+            [_bars addObject:bar];
+            [self addSubview:bar];
+        }
+
+        //Height Of Bar
+        float value = [valueString floatValue];
+        float grade =fabsf((float)value / (float)_yValueMax);
+
+        if (isnan(grade)) {
+            grade = 0;
+        }
+        bar.maxDivisor = (float)_yValueMax;
+        bar.grade = grade;
+        bar.isShowNumber = self.isShowNumbers;
+        CGRect originalFrame = bar.frame;
+        NSString *currentNumber =  [NSString stringWithFormat:@"%f",value];
+
+        if ([[currentNumber substringToIndex:1] isEqualToString:@"-"] && self.showLevelLine) {
+        CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);
+        [bar setTransform:transform];
+        originalFrame.origin.y = bar.frame.origin.y + bar.frame.size.height;
+        bar.frame = originalFrame;
+        bar.isNegative = YES;
+
+      }
+      index += 1;
+    }
+}
+
+- (void)strokeChart
+{
+    //Add Labels
+
+    [self viewCleanupForCollection:_bars];
+
+
+    //Update Bar
+
+    [self updateBar];
+
+    //Add chart border lines
+
+    if (_showChartBorder) {
+        _chartBottomLine = [CAShapeLayer layer];
+        _chartBottomLine.lineCap      = kCALineCapButt;
+        _chartBottomLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartBottomLine.lineWidth    = 1.0;
+        _chartBottomLine.strokeEnd    = 0.0;
+
+        UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+        [progressline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+        [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginRight,  self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+
+        [progressline setLineWidth:1.0];
+        [progressline setLineCapStyle:kCGLineCapSquare];
+        _chartBottomLine.path = progressline.CGPath;
+        _chartBottomLine.strokeColor = [_chartBorderColor CGColor];;
+        _chartBottomLine.strokeEnd = 1.0;
+
+        [self.layer addSublayer:_chartBottomLine];
+
+        //Add left Chart Line
+
+        _chartLeftLine = [CAShapeLayer layer];
+        _chartLeftLine.lineCap      = kCALineCapButt;
+        _chartLeftLine.fillColor    = [[UIColor whiteColor] CGColor];
+        _chartLeftLine.lineWidth    = 1.0;
+        _chartLeftLine.strokeEnd    = 0.0;
+
+        UIBezierPath *progressLeftline = [UIBezierPath bezierPath];
+
+        [progressLeftline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)];
+        [progressLeftline addLineToPoint:CGPointMake(_chartMarginLeft,  _chartMarginTop)];
+
+        [progressLeftline setLineWidth:1.0];
+        [progressLeftline setLineCapStyle:kCGLineCapSquare];
+        _chartLeftLine.path = progressLeftline.CGPath;
+        _chartLeftLine.strokeColor = [_chartBorderColor CGColor];
+        _chartLeftLine.strokeEnd = 1.0;
+
+        [self addBorderAnimationIfNeeded];
+        [self.layer addSublayer:_chartLeftLine];
+    }
+
+  // Add Level Separator Line
+  if (_showLevelLine) {
+    _chartLevelLine = [CAShapeLayer layer];
+    _chartLevelLine.lineCap      = kCALineCapButt;
+    _chartLevelLine.fillColor    = [[UIColor whiteColor] CGColor];
+    _chartLevelLine.lineWidth    = 1.0;
+    _chartLevelLine.strokeEnd    = 0.0;
+
+    UIBezierPath *progressline = [UIBezierPath bezierPath];
+
+    [progressline moveToPoint:CGPointMake(_chartMarginLeft, (self.frame.size.height - kXLabelHeight )/2.0)];
+    [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginLeft - _chartMarginRight,  (self.frame.size.height - kXLabelHeight )/2.0)];
+
+    [progressline setLineWidth:1.0];
+    [progressline setLineCapStyle:kCGLineCapSquare];
+    _chartLevelLine.path = progressline.CGPath;
+
+    _chartLevelLine.strokeColor = PNLightGrey.CGColor;
+      
+    [self addSeparatorAnimationIfNeeded];
+    _chartLevelLine.strokeEnd = 1.0;
+
+    [self.layer addSublayer:_chartLevelLine];
+  } else {
+    if (_chartLevelLine) {
+      [_chartLevelLine removeFromSuperlayer];
+      _chartLevelLine = nil;
+    }
+  }
+}
+
+- (void)addBorderAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = 0.5;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @0.0f;
+        pathAnimation.toValue = @1.0f;
+        [_chartBottomLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        
+        CABasicAnimation *pathLeftAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathLeftAnimation.duration = 0.5;
+        pathLeftAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathLeftAnimation.fromValue = @0.0f;
+        pathLeftAnimation.toValue = @1.0f;
+        [_chartLeftLine addAnimation:pathLeftAnimation forKey:@"strokeEndAnimation"];
+    }
+}
+
+- (void)addSeparatorAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = 0.5;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @0.0f;
+        pathAnimation.toValue = @1.0f;
+        [_chartLevelLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+    }
+}
+
+- (void)viewCleanupForCollection:(NSMutableArray *)array
+{
+    if (array.count) {
+        [array makeObjectsPerformSelector:@selector(removeFromSuperview)];
+        [array removeAllObjects];
+    }
+}
+
+
+#pragma mark - Class extension methods
+
+- (UIColor *)barColorAtIndex:(NSUInteger)index
+{
+    if ([self.strokeColors count] == [self.yValues count]) {
+        return self.strokeColors[index];
+    }
+    else {
+        return self.strokeColor;
+    }
+}
+
+#pragma mark - Touch detection
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    [self touchPoint:touches withEvent:event];
+    [super touchesBegan:touches withEvent:event];
+}
+
+- (void)touchPoint:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    //Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+    UIView *subview = [self hitTest:touchPoint withEvent:nil];
+
+    if ([subview isKindOfClass:[PNBar class]] && [self.delegate respondsToSelector:@selector(userClickedOnBarAtIndex:)]) {
+        [self.delegate userClickedOnBarAtIndex:subview.tag];
+    }
+}
+
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNChart.h b/PNChartdemo/PNChartdemo/PNChart/PNChart.h
new file mode 100755
index 0000000..0835d39
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNChart.h
@@ -0,0 +1,22 @@
+//
+//  PNChart.h
+//	Version 0.1
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNChart.h"
+#import "PNColor.h"
+#import "PNLineChart.h"
+#import "PNLineChartData.h"
+#import "PNLineChartDataItem.h"
+#import "PNBarChart.h"
+#import "PNCircleChart.h"
+#import "PNChartDelegate.h"
+#import "PNPieChart.h"
+#import "PNScatterChart.h"
+#import "PNRadarChart.h"
+#import "PNRadarChartDataItem.h"
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNChartDelegate.h b/PNChartdemo/PNChartdemo/PNChart/PNChartDelegate.h
new file mode 100755
index 0000000..6d49f7c
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNChartDelegate.h
@@ -0,0 +1,33 @@
+//
+//  PNChartDelegate.h
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-12-11.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol PNChartDelegate <NSObject>
+@optional
+/**
+ * Callback method that gets invoked when the user taps on the chart line.
+ */
+- (void)userClickedOnLinePoint:(CGPoint)point lineIndex:(NSInteger)lineIndex;
+
+/**
+ * Callback method that gets invoked when the user taps on a chart line key point.
+ */
+- (void)userClickedOnLineKeyPoint:(CGPoint)point
+                        lineIndex:(NSInteger)lineIndex
+                       pointIndex:(NSInteger)pointIndex;
+
+/**
+ * Callback method that gets invoked when the user taps on a chart bar.
+ */
+- (void)userClickedOnBarAtIndex:(NSInteger)barIndex;
+
+
+- (void)userClickedOnPieIndexItem:(NSInteger)pieIndex;
+- (void)didUnselectPieItem;
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.h b/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.h
new file mode 100755
index 0000000..9ba6afa
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.h
@@ -0,0 +1,13 @@
+//
+//  PNChartLabel.h
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface PNChartLabel : UILabel
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.m b/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.m
new file mode 100755
index 0000000..b0980d1
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNChartLabel.m
@@ -0,0 +1,32 @@
+//
+//  PNChartLabel.m
+//  PNChart
+//
+//  Created by kevin on 10/3/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNChartLabel.h"
+
+@implementation PNChartLabel
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        self.font                      = [UIFont boldSystemFontOfSize:11.0f];
+        self.backgroundColor           = [UIColor clearColor];
+        self.textAlignment             = NSTextAlignmentCenter;
+        self.userInteractionEnabled    = YES;
+        self.adjustsFontSizeToFitWidth = YES;
+        self.numberOfLines             = 0;
+        /* if you want to see ... in large labels un-comment this line
+        self.minimumScaleFactor        = 0.8;
+        */
+    }
+
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.h b/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.h
new file mode 100755
index 0000000..0c57376
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.h
@@ -0,0 +1,74 @@
+//
+//  PNCircleChart.h
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-11-30.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNColor.h"
+#import <UICountingLabel/UICountingLabel.h>
+
+typedef NS_ENUM (NSUInteger, PNChartFormatType) {
+    PNChartFormatTypePercent,
+    PNChartFormatTypeDollar,
+    PNChartFormatTypeNone,
+    PNChartFormatTypeDecimal,
+    PNChartFormatTypeDecimalTwoPlaces,
+};
+
+#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
+
+@interface PNCircleChart : UIView
+
+- (void)strokeChart;
+- (void)growChartByAmount:(NSNumber *)growAmount;
+- (void)updateChartByCurrent:(NSNumber *)current;
+- (void)updateChartByCurrent:(NSNumber *)current byTotal:(NSNumber *)total;
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel;
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel
+  overrideLineWidth:(NSNumber *)overrideLineWidth;
+
+@property (strong, nonatomic) UICountingLabel *countingLabel;
+@property (nonatomic) UIColor *strokeColor;
+@property (nonatomic) UIColor *strokeColorGradientStart;
+@property (nonatomic) NSNumber *total;
+@property (nonatomic) NSNumber *current;
+@property (nonatomic) NSNumber *lineWidth;
+@property (nonatomic) NSTimeInterval duration;
+@property (nonatomic) PNChartFormatType chartType;
+
+@property (nonatomic) CAShapeLayer *circle;
+@property (nonatomic) CAShapeLayer *gradientMask;
+@property (nonatomic) CAShapeLayer *circleBackground;
+
+@property (nonatomic) BOOL displayCountingLabel;
+@property (nonatomic) BOOL displayAnimated;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.m b/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.m
new file mode 100755
index 0000000..19f70e5
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNCircleChart.m
@@ -0,0 +1,267 @@
+//
+//  PNCircleChart.m
+//  PNChartDemo
+//
+//  Created by kevinzhow on 13-11-30.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNCircleChart.h"
+
+@interface PNCircleChart ()
+@end
+
+@implementation PNCircleChart
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:NO
+                   shadowColor:[UIColor clearColor]
+          displayCountingLabel:YES
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:shadow
+                   shadowColor:backgroundShadowColor
+          displayCountingLabel:YES
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor displayCountingLabel:(BOOL)displayCountingLabel {
+    
+    return [self initWithFrame:frame
+                         total:total
+                       current:current
+                     clockwise:clockwise
+                        shadow:shadow
+                   shadowColor:backgroundShadowColor
+          displayCountingLabel:displayCountingLabel
+             overrideLineWidth:@8.0f];
+    
+}
+
+- (id)initWithFrame:(CGRect)frame
+              total:(NSNumber *)total
+            current:(NSNumber *)current
+          clockwise:(BOOL)clockwise
+             shadow:(BOOL)hasBackgroundShadow
+        shadowColor:(UIColor *)backgroundShadowColor
+displayCountingLabel:(BOOL)displayCountingLabel
+  overrideLineWidth:(NSNumber *)overrideLineWidth
+{
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        _total = total;
+        _current = current;
+        _strokeColor = PNFreshGreen;
+        _duration = 1.0;
+        _chartType = PNChartFormatTypePercent;
+        _displayAnimated = YES;
+        
+        _displayCountingLabel = displayCountingLabel;
+
+        CGFloat startAngle = clockwise ? -90.0f : 270.0f;
+        CGFloat endAngle = clockwise ? -90.01f : 270.01f;
+
+        _lineWidth = overrideLineWidth;
+        
+        UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)
+                                                                  radius:(self.frame.size.height * 0.5) - ([_lineWidth floatValue]/2.0f)
+                                                              startAngle:DEGREES_TO_RADIANS(startAngle)
+                                                                endAngle:DEGREES_TO_RADIANS(endAngle)
+                                                               clockwise:clockwise];
+
+        _circle               = [CAShapeLayer layer];
+        _circle.path          = circlePath.CGPath;
+        _circle.lineCap       = kCALineCapRound;
+        _circle.fillColor     = [UIColor clearColor].CGColor;
+        _circle.lineWidth     = [_lineWidth floatValue];
+        _circle.zPosition     = 1;
+
+        _circleBackground             = [CAShapeLayer layer];
+        _circleBackground.path        = circlePath.CGPath;
+        _circleBackground.lineCap     = kCALineCapRound;
+        _circleBackground.fillColor   = [UIColor clearColor].CGColor;
+        _circleBackground.lineWidth   = [_lineWidth floatValue];
+        _circleBackground.strokeColor = (hasBackgroundShadow ? backgroundShadowColor.CGColor : [UIColor clearColor].CGColor);
+        _circleBackground.strokeEnd   = 1.0;
+        _circleBackground.zPosition   = -1;
+
+        [self.layer addSublayer:_circle];
+        [self.layer addSublayer:_circleBackground];
+
+        _countingLabel = [[UICountingLabel alloc] initWithFrame:CGRectMake(0, 0, 100.0, 50.0)];
+        [_countingLabel setTextAlignment:NSTextAlignmentCenter];
+        [_countingLabel setFont:[UIFont boldSystemFontOfSize:16.0f]];
+        [_countingLabel setTextColor:[UIColor grayColor]];
+        [_countingLabel setBackgroundColor:[UIColor clearColor]];
+        [_countingLabel setCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)];
+        _countingLabel.method = UILabelCountingMethodEaseInOut;
+        if (_displayCountingLabel) {
+            [self addSubview:_countingLabel];
+        }
+    }
+
+    return self;
+}
+
+
+- (void)strokeChart
+{
+    // Add counting label
+
+    if (_displayCountingLabel) {
+        NSString *format;
+        switch (self.chartType) {
+            case PNChartFormatTypePercent:
+                format = @"%d%%";
+                break;
+            case PNChartFormatTypeDollar:
+                format = @"$%d";
+                break;
+            case PNChartFormatTypeDecimal:
+                format = @"%.1f";
+                break;
+            case PNChartFormatTypeDecimalTwoPlaces:
+                format = @"%.2f";
+                break;
+            case PNChartFormatTypeNone:
+            default:
+                format = @"%d";
+                break;
+        }
+        self.countingLabel.format = format;
+        [self addSubview:self.countingLabel];
+    }
+
+
+    // Add circle params
+
+    _circle.lineWidth   = [_lineWidth floatValue];
+    _circleBackground.lineWidth = [_lineWidth floatValue];
+    _circleBackground.strokeEnd = 1.0;
+    _circle.strokeColor = _strokeColor.CGColor;
+    _circle.strokeEnd   = [_current floatValue] / [_total floatValue];
+
+    // Check if user wants to add a gradient from the start color to the bar color
+    if (_strokeColorGradientStart) {
+
+        // Add gradient
+        self.gradientMask = [CAShapeLayer layer];
+        self.gradientMask.fillColor = [[UIColor clearColor] CGColor];
+        self.gradientMask.strokeColor = [[UIColor blackColor] CGColor];
+        self.gradientMask.lineWidth = _circle.lineWidth;
+        self.gradientMask.lineCap = kCALineCapRound;
+        CGRect gradientFrame = CGRectMake(0, 0, 2*self.bounds.size.width, 2*self.bounds.size.height);
+        self.gradientMask.frame = gradientFrame;
+        self.gradientMask.path = _circle.path;
+
+        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
+        gradientLayer.startPoint = CGPointMake(0.5,1.0);
+        gradientLayer.endPoint = CGPointMake(0.5,0.0);
+        gradientLayer.frame = gradientFrame;
+        UIColor *endColor = (_strokeColor ? _strokeColor : [UIColor greenColor]);
+        NSArray *colors = @[
+                            (id)endColor.CGColor,
+                            (id)_strokeColorGradientStart.CGColor
+                            ];
+        gradientLayer.colors = colors;
+
+        [gradientLayer setMask:self.gradientMask];
+
+        [_circle addSublayer:gradientLayer];
+
+        self.gradientMask.strokeEnd = [_current floatValue] / [_total floatValue];
+    }
+    
+    [self addAnimationIfNeeded];
+}
+
+
+
+- (void)growChartByAmount:(NSNumber *)growAmount
+{
+    NSNumber *updatedValue = [NSNumber numberWithFloat:[_current floatValue] + [growAmount floatValue]];
+
+    // Add animation
+    [self updateChartByCurrent:updatedValue];
+}
+
+
+-(void)updateChartByCurrent:(NSNumber *)current{
+    
+    [self updateChartByCurrent:current
+                       byTotal:_total];
+    
+}
+
+-(void)updateChartByCurrent:(NSNumber *)current byTotal:(NSNumber *)total {
+    double totalPercentageValue = [current floatValue]/([total floatValue]/100.0);
+    
+    if (_strokeColorGradientStart) {
+        self.gradientMask.strokeEnd = _circle.strokeEnd;
+    }
+    
+    // Add animation
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = self.duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @([_current floatValue] / [_total floatValue]);
+        pathAnimation.toValue = @([current floatValue] / [total floatValue]);
+        
+        if (_strokeColorGradientStart) {
+            [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+        [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        
+        if (_displayCountingLabel) {
+            [self.countingLabel countFrom:fmin([_current floatValue], [_total floatValue]) to:totalPercentageValue withDuration:self.duration];
+        }
+        
+    }
+    else if (_displayCountingLabel) {
+        [self.countingLabel countFrom:totalPercentageValue to:totalPercentageValue withDuration:self.duration];
+    }
+    
+    _circle.strokeEnd   = [current floatValue] / [total floatValue];
+    _current = current;
+    _total = total;
+}
+
+- (void)addAnimationIfNeeded
+{
+    double percentageValue = [_current floatValue]/([_total floatValue]/100.0);
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        pathAnimation.duration = self.duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @(0.0f);
+        pathAnimation.toValue = @([_current floatValue] / [_total floatValue]);
+        [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        [_countingLabel countFrom:0 to:percentageValue withDuration:self.duration];
+        
+        if (self.gradientMask && _strokeColorGradientStart) {
+            [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
+        }
+    }
+    else {
+        [_countingLabel countFrom:percentageValue to:percentageValue withDuration:self.duration];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNColor.h b/PNChartdemo/PNChartdemo/PNChart/PNColor.h
new file mode 100755
index 0000000..cfd3ff8
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNColor.h
@@ -0,0 +1,53 @@
+//
+//  PNColor.h
+//  PNChart
+//
+//  Created by kevin on 13-6-8.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+/*
+ *  System Versioning Preprocessor Macros
+ */
+
+#define SCREEN_WIDTH    ([UIScreen mainScreen].bounds.size.width)
+
+#define PNGrey          [UIColor colorWithRed:246.0 / 255.0 green:246.0 / 255.0 blue:246.0 / 255.0 alpha:1.0f]
+#define PNLightBlue     [UIColor colorWithRed:94.0 / 255.0 green:147.0 / 255.0 blue:196.0 / 255.0 alpha:1.0f]
+#define PNGreen         [UIColor colorWithRed:77.0 / 255.0 green:186.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNTitleColor    [UIColor colorWithRed:0.0 / 255.0 green:189.0 / 255.0 blue:113.0 / 255.0 alpha:1.0f]
+#define PNButtonGrey    [UIColor colorWithRed:141.0 / 255.0 green:141.0 / 255.0 blue:141.0 / 255.0 alpha:1.0f]
+#define PNLightGreen    [UIColor colorWithRed:77.0 / 255.0 green:216.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNFreshGreen    [UIColor colorWithRed:77.0 / 255.0 green:196.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNDeepGreen     [UIColor colorWithRed:77.0 / 255.0 green:176.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f]
+#define PNRed           [UIColor colorWithRed:245.0 / 255.0 green:94.0 / 255.0 blue:78.0 / 255.0 alpha:1.0f]
+#define PNMauve         [UIColor colorWithRed:88.0 / 255.0 green:75.0 / 255.0 blue:103.0 / 255.0 alpha:1.0f]
+#define PNBrown         [UIColor colorWithRed:119.0 / 255.0 green:107.0 / 255.0 blue:95.0 / 255.0 alpha:1.0f]
+#define PNBlue          [UIColor colorWithRed:82.0 / 255.0 green:116.0 / 255.0 blue:188.0 / 255.0 alpha:1.0f]
+#define PNDarkBlue      [UIColor colorWithRed:121.0 / 255.0 green:134.0 / 255.0 blue:142.0 / 255.0 alpha:1.0f]
+#define PNYellow        [UIColor colorWithRed:242.0 / 255.0 green:197.0 / 255.0 blue:117.0 / 255.0 alpha:1.0f]
+#define PNWhite         [UIColor colorWithRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:1.0f]
+#define PNDeepGrey      [UIColor colorWithRed:99.0 / 255.0 green:99.0 / 255.0 blue:99.0 / 255.0 alpha:1.0f]
+#define PNPinkGrey      [UIColor colorWithRed:200.0 / 255.0 green:193.0 / 255.0 blue:193.0 / 255.0 alpha:1.0f]
+#define PNHealYellow    [UIColor colorWithRed:245.0 / 255.0 green:242.0 / 255.0 blue:238.0 / 255.0 alpha:1.0f]
+#define PNLightGrey     [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:225.0 / 255.0 alpha:1.0f]
+#define PNCleanGrey     [UIColor colorWithRed:251.0 / 255.0 green:251.0 / 255.0 blue:251.0 / 255.0 alpha:1.0f]
+#define PNLightYellow   [UIColor colorWithRed:241.0 / 255.0 green:240.0 / 255.0 blue:240.0 / 255.0 alpha:1.0f]
+#define PNDarkYellow    [UIColor colorWithRed:152.0 / 255.0 green:150.0 / 255.0 blue:159.0 / 255.0 alpha:1.0f]
+#define PNPinkDark      [UIColor colorWithRed:170.0 / 255.0 green:165.0 / 255.0 blue:165.0 / 255.0 alpha:1.0f]
+#define PNCloudWhite    [UIColor colorWithRed:244.0 / 255.0 green:244.0 / 255.0 blue:244.0 / 255.0 alpha:1.0f]
+#define PNBlack         [UIColor colorWithRed:45.0 / 255.0 green:45.0 / 255.0 blue:45.0 / 255.0 alpha:1.0f]
+#define PNStarYellow    [UIColor colorWithRed:252.0 / 255.0 green:223.0 / 255.0 blue:101.0 / 255.0 alpha:1.0f]
+#define PNTwitterColor  [UIColor colorWithRed:0.0 / 255.0 green:171.0 / 255.0 blue:243.0 / 255.0 alpha:1.0]
+#define PNWeiboColor    [UIColor colorWithRed:250.0 / 255.0 green:0.0 / 255.0 blue:33.0 / 255.0 alpha:1.0]
+#define PNiOSGreenColor [UIColor colorWithRed:98.0 / 255.0 green:247.0 / 255.0 blue:77.0 / 255.0 alpha:1.0]
+
+
+@interface PNColor : NSObject
+
+- (UIImage *)imageFromColor:(UIColor *)color;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNColor.m b/PNChartdemo/PNChartdemo/PNChart/PNColor.m
new file mode 100755
index 0000000..2ebc8c0
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNColor.m
@@ -0,0 +1,29 @@
+//
+//  PNColor.m
+//  PNChart
+//
+//  Created by kevin on 13-6-8.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNColor.h"
+#import <UIKit/UIKit.h>
+
+@implementation PNColor
+
+- (UIImage *)imageFromColor:(UIColor *)color
+{
+    CGRect rect = CGRectMake(0, 0, 1, 1);
+
+    UIGraphicsBeginImageContext(rect.size);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextSetFillColorWithColor(context, [color CGColor]);
+    CGContextFillRect(context, rect);
+    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+
+    return img;
+}
+
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.h b/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.h
new file mode 100755
index 0000000..829d84a
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.h
@@ -0,0 +1,48 @@
+//
+//  PNGenericChart.h
+//  PNChartDemo
+//
+//  Created by Andi Palo on 26/02/15.
+//  Copyright (c) 2015 kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNLegendPosition) {
+    PNLegendPositionTop = 0,
+    PNLegendPositionBottom = 1,
+    PNLegendPositionLeft = 2,
+    PNLegendPositionRight = 3
+};
+
+typedef NS_ENUM(NSUInteger, PNLegendItemStyle) {
+    PNLegendItemStyleStacked = 0,
+    PNLegendItemStyleSerial = 1
+};
+
+@interface PNGenericChart : UIView
+
+@property (assign, nonatomic) BOOL hasLegend;
+@property (assign, nonatomic) PNLegendPosition legendPosition;
+@property (assign, nonatomic) PNLegendItemStyle legendStyle;
+
+@property (assign, nonatomic) UIFont *legendFont;
+@property (assign, nonatomic) UIColor *legendFontColor;
+@property (assign, nonatomic) NSUInteger labelRowsInSerialMode;
+
+/** Display the chart with or without animation. Default is YES. **/
+@property (nonatomic) BOOL displayAnimated;
+
+/**
+ *  returns the Legend View, or nil if no chart data is present.
+ *  The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect)
+ *
+ *  @param mWidth Maximum width of legend. Height will depend on this and font size
+ *
+ *  @return UIView of Legend
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth;
+
+
+- (void) setupDefaultValues;
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.m b/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.m
new file mode 100755
index 0000000..c54ac37
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNGenericChart.m
@@ -0,0 +1,54 @@
+//
+//  PNGenericChart.m
+//  PNChartDemo
+//
+//  Created by Andi Palo on 26/02/15.
+//  Copyright (c) 2015 kevinzhow. All rights reserved.
+//
+
+#import "PNGenericChart.h"
+
+@interface PNGenericChart ()
+
+
+
+@end
+
+@implementation PNGenericChart
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+- (void) setupDefaultValues{
+    self.hasLegend = YES;
+    self.legendPosition = PNLegendPositionBottom;
+    self.legendStyle = PNLegendItemStyleStacked;
+    self.labelRowsInSerialMode = 1;
+    self.displayAnimated = YES;
+}
+
+
+
+/**
+ *  to be implemented in subclass 
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{
+    [self doesNotRecognizeSelector:_cmd];
+    return nil;
+}
+
+- (void) setLabelRowsInSerialMode:(NSUInteger)num{
+    if (self.legendStyle == PNLegendItemStyleSerial) {
+        _labelRowsInSerialMode = num;
+    }else{
+        _labelRowsInSerialMode = 1;
+    }
+}
+
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChart.h b/PNChartdemo/PNChartdemo/PNChart/PNLineChart.h
new file mode 100755
index 0000000..b30878a
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChart.h
@@ -0,0 +1,110 @@
+//
+//  PNLineChart.h
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "PNChartDelegate.h"
+#import "PNGenericChart.h"
+
+@interface PNLineChart : PNGenericChart
+
+/**
+ * Draws the chart in an animated fashion.
+ */
+- (void)strokeChart;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+@property (nonatomic) NSArray *xLabels;
+@property (nonatomic) NSArray *yLabels;
+
+/**
+ * Array of `LineChartData` objects, one for each line.
+ */
+@property (nonatomic) NSArray *chartData;
+
+@property (nonatomic) NSMutableArray *pathPoints;
+@property (nonatomic) NSMutableArray *xChartLabels;
+@property (nonatomic) NSMutableArray *yChartLabels;
+
+@property (nonatomic) CGFloat xLabelWidth;
+@property (nonatomic) UIFont *xLabelFont;
+@property (nonatomic) UIColor *xLabelColor;
+@property (nonatomic) CGFloat yValueMax;
+@property (nonatomic) CGFloat yFixedValueMax;
+@property (nonatomic) CGFloat yFixedValueMin;
+@property (nonatomic) CGFloat yValueMin;
+@property (nonatomic) NSInteger yLabelNum;
+@property (nonatomic) CGFloat yLabelHeight;
+@property (nonatomic) UIFont *yLabelFont;
+@property (nonatomic) UIColor *yLabelColor;
+@property (nonatomic) CGFloat chartCavanHeight;
+@property (nonatomic) CGFloat chartCavanWidth;
+@property (nonatomic) BOOL showLabel;
+@property (nonatomic) BOOL showGenYLabels;
+@property (nonatomic) BOOL showYGridLines;
+@property (nonatomic) UIColor *yGridLinesColor;
+@property (nonatomic) BOOL thousandsSeparator;
+
+@property (nonatomic) CGFloat chartMarginLeft;
+@property (nonatomic) CGFloat chartMarginRight;
+@property (nonatomic) CGFloat chartMarginTop;
+@property (nonatomic) CGFloat chartMarginBottom;
+
+/**
+ * Controls whether to show the coordinate axis. Default is NO.
+ */
+@property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis;
+@property (nonatomic) UIColor *axisColor;
+@property (nonatomic) CGFloat axisWidth;
+
+@property (nonatomic, strong) NSString *xUnit;
+@property (nonatomic, strong) NSString *yUnit;
+
+/**
+ * String formatter for float values in y-axis labels. If not set, defaults to @"%1.f"
+ */
+@property (nonatomic, strong) NSString *yLabelFormat;
+
+/**
+ * Block formatter for custom string in y-axis labels. If not set, defaults to yLabelFormat
+ */
+@property (nonatomic, copy) NSString* (^yLabelBlockFormatter)(CGFloat);
+
+
+/**
+ * Controls whether to curve the line chart or not
+ */
+@property (nonatomic) BOOL showSmoothLines;
+
+- (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width;
+
+/**
+ * Update Chart Value
+ */
+
+- (void)updateChartData:(NSArray *)data;
+
+
+/**
+ *  returns the Legend View, or nil if no chart data is present. 
+ *  The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect)
+ *
+ *  @param mWidth Maximum width of legend. Height will depend on this and font size
+ *
+ *  @return UIView of Legend
+ */
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth;
+
+
++ (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font;
+
++ (CGPoint)midPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2;
++ (CGPoint)controlPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChart.m b/PNChartdemo/PNChartdemo/PNChart/PNLineChart.m
new file mode 100755
index 0000000..d03e494
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChart.m
@@ -0,0 +1,1284 @@
+//
+//  PNLineChart.m
+//  PNChartDemo
+//
+//  Created by kevin on 11/7/13.
+//  Copyright (c) 2013��� kevinzhow. All rights reserved.
+//
+
+#import "PNLineChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+#import "PNLineChartData.h"
+#import "PNLineChartDataItem.h"
+
+@interface PNLineChart ()
+
+@property(nonatomic) NSMutableArray *chartLineArray;  // Array[CAShapeLayer]
+@property(nonatomic) NSMutableArray *chartPointArray; // Array[CAShapeLayer] save the point layer
+
+@property(nonatomic) NSMutableArray *chartPath;       // Array of line path, one for each line.
+@property(nonatomic) NSMutableArray *pointPath;       // Array of point path, one for each line
+@property(nonatomic) NSMutableArray *endPointsOfPath;      // Array of start and end points of each line path, one for each line
+
+@property(nonatomic) CABasicAnimation *pathAnimation; // will be set to nil if _displayAnimation is NO
+
+// display grade
+@property(nonatomic) NSMutableArray *gradeStringPaths;
+@property(nonatomic) NSMutableArray *progressLinePathsColors; //Array of colors when drawing each line.if chartData.rangeColors is set then different colors will be
+
+@end
+
+@implementation PNLineChart
+
+@synthesize pathAnimation = _pathAnimation;
+
+#pragma mark initialization
+
+- (id)initWithCoder:(NSCoder *)coder {
+    self = [super initWithCoder:coder];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+
+    if (self) {
+        [self setupDefaultValues];
+    }
+
+    return self;
+}
+
+
+#pragma mark instance methods
+
+- (void)setYLabels {
+    CGFloat yStep = (_yValueMax - _yValueMin) / _yLabelNum;
+    CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+
+    if (_yChartLabels) {
+        for (PNChartLabel *label in _yChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _yChartLabels = [NSMutableArray new];
+    }
+
+    if (yStep == 0.0) {
+        PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger) _chartCavanHeight, (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        minLabel.text = [self formatYLabel:0.0];
+        [self setCustomStyleForYLabel:minLabel];
+        [self addSubview:minLabel];
+        [_yChartLabels addObject:minLabel];
+
+        PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger) (_chartCavanHeight / 2), (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        midLabel.text = [self formatYLabel:_yValueMax];
+        [self setCustomStyleForYLabel:midLabel];
+        [self addSubview:midLabel];
+        [_yChartLabels addObject:midLabel];
+
+        PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger) _chartMarginBottom, (NSInteger) _yLabelHeight)];
+        maxLabel.text = [self formatYLabel:_yValueMax * 2];
+        [self setCustomStyleForYLabel:maxLabel];
+        [self addSubview:maxLabel];
+        [_yChartLabels addObject:maxLabel];
+
+    } else {
+        NSInteger index = 0;
+        NSInteger num = _yLabelNum + 1;
+
+        while (num > 0) {
+            CGRect labelFrame = CGRectMake(0.0,
+                    (NSInteger) (_chartCavanHeight + _chartMarginTop - index * yStepHeight),
+                    (CGFloat) ((NSInteger) _chartMarginLeft * 0.9),
+                    (NSInteger) _yLabelHeight);
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:labelFrame];
+            [label setTextAlignment:NSTextAlignmentRight];
+            label.text = [self formatYLabel:_yValueMin + (yStep * index)];
+            [self setCustomStyleForYLabel:label];
+            [self addSubview:label];
+            [_yChartLabels addObject:label];
+            index += 1;
+            num -= 1;
+        }
+    }
+}
+
+- (void)setYLabels:(NSArray *)yLabels {
+    _showGenYLabels = NO;
+    _yLabelNum = yLabels.count - 1;
+
+    CGFloat yLabelHeight;
+    if (_showLabel) {
+        yLabelHeight = _chartCavanHeight / [yLabels count];
+    } else {
+        yLabelHeight = (self.frame.size.height) / [yLabels count];
+    }
+
+    return [self setYLabels:yLabels withHeight:yLabelHeight];
+}
+
+- (void)setYLabels:(NSArray *)yLabels withHeight:(CGFloat)height {
+    _yLabels = yLabels;
+    _yLabelHeight = height;
+    if (_yChartLabels) {
+        for (PNChartLabel *label in _yChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _yChartLabels = [NSMutableArray new];
+    }
+
+    NSString *labelText;
+
+    if (_showLabel) {
+        CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+
+        for (int index = 0; index < yLabels.count; index++) {
+            labelText = yLabels[(NSUInteger) index];
+
+            NSInteger y = (NSInteger) (_chartCavanHeight + _chartMarginTop - index * yStepHeight);
+
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, y, (CGFloat) ((NSInteger) _chartMarginLeft * 0.9), (NSInteger) _yLabelHeight)];
+            [label setTextAlignment:NSTextAlignmentRight];
+            label.text = labelText;
+            [self setCustomStyleForYLabel:label];
+            [self addSubview:label];
+            [_yChartLabels addObject:label];
+        }
+    }
+}
+
+- (CGFloat)computeEqualWidthForXLabels:(NSArray *)xLabels {
+    CGFloat xLabelWidth;
+
+    if (_showLabel) {
+        xLabelWidth = _chartCavanWidth / [xLabels count];
+    } else {
+        xLabelWidth = (self.frame.size.width) / [xLabels count];
+    }
+
+    return xLabelWidth;
+}
+
+
+- (void)setXLabels:(NSArray *)xLabels {
+    CGFloat xLabelWidth;
+
+    if (_showLabel) {
+        xLabelWidth = _chartCavanWidth / [xLabels count];
+    } else {
+        xLabelWidth = (self.frame.size.width - _chartMarginLeft - _chartMarginRight) / [xLabels count];
+    }
+
+    return [self setXLabels:xLabels withWidth:xLabelWidth];
+}
+
+- (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width {
+    _xLabels = xLabels;
+    _xLabelWidth = width;
+    if (_xChartLabels) {
+        for (PNChartLabel *label in _xChartLabels) {
+            [label removeFromSuperview];
+        }
+    } else {
+        _xChartLabels = [NSMutableArray new];
+    }
+
+    NSString *labelText;
+
+    if (_showLabel) {
+        for (NSUInteger index = 0; index < xLabels.count; index++) {
+            labelText = xLabels[index];
+
+            NSInteger x = (NSInteger) (index * _xLabelWidth + _chartMarginLeft);
+            NSInteger y = (NSInteger) (_chartMarginBottom + _chartCavanHeight);
+
+            PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(x, y, (NSInteger) _xLabelWidth, (NSInteger) _chartMarginBottom)];
+            [label setTextAlignment:NSTextAlignmentCenter];
+            label.text = labelText;
+            [self setCustomStyleForXLabel:label];
+            [self addSubview:label];
+            [_xChartLabels addObject:label];
+        }
+    }
+}
+
+- (void)setCustomStyleForXLabel:(UILabel *)label {
+    if (_xLabelFont) {
+        label.font = _xLabelFont;
+    }
+
+    if (_xLabelColor) {
+        label.textColor = _xLabelColor;
+    }
+
+}
+
+- (void)setCustomStyleForYLabel:(UILabel *)label {
+    if (_yLabelFont) {
+        label.font = _yLabelFont;
+    }
+
+    if (_yLabelColor) {
+        label.textColor = _yLabelColor;
+    }
+}
+
+#pragma mark - Touch at point
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+    [self touchPoint:touches withEvent:event];
+    [self touchKeyPoint:touches withEvent:event];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+    [self touchPoint:touches withEvent:event];
+    [self touchKeyPoint:touches withEvent:event];
+}
+
+- (void)touchPoint:(NSSet *)touches withEvent:(UIEvent *)event {
+    // Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+
+    for (NSUInteger p = 0; p < _pathPoints.count; p++) {
+        NSArray *linePointsArray = _endPointsOfPath[p];
+
+        for (NSUInteger i = 0; i < (int) linePointsArray.count - 1; i += 2) {
+            CGPoint p1 = [linePointsArray[i] CGPointValue];
+            CGPoint p2 = [linePointsArray[i + 1] CGPointValue];
+
+            // Closest distance from point to line
+            float distance = (float) fabs(((p2.x - p1.x) * (touchPoint.y - p1.y)) - ((p1.x - touchPoint.x) * (p1.y - p2.y)));
+            distance /= hypot(p2.x - p1.x, p1.y - p2.y);
+
+            if (distance <= 5.0) {
+                // Conform to delegate parameters, figure out what bezier path this CGPoint belongs to.
+                NSUInteger lineIndex = 0;
+                for (NSArray<UIBezierPath *> *paths in _chartPath) {
+                    for (UIBezierPath *path in paths) {
+                        BOOL pointContainsPath = CGPathContainsPoint(path.CGPath, NULL, p1, NO);
+                        if (pointContainsPath) {
+                            [_delegate userClickedOnLinePoint:touchPoint lineIndex:lineIndex];
+                            return;
+                        }
+                    }
+                    lineIndex++;
+                }
+            }
+        }
+    }
+}
+
+- (void)touchKeyPoint:(NSSet *)touches withEvent:(UIEvent *)event {
+    // Get the point user touched
+    UITouch *touch = [touches anyObject];
+    CGPoint touchPoint = [touch locationInView:self];
+
+    for (NSUInteger p = 0; p < _pathPoints.count; p++) {
+        NSArray *linePointsArray = _pathPoints[p];
+
+        for (NSUInteger i = 0; i < (int) linePointsArray.count - 1; i += 1) {
+            CGPoint p1 = [linePointsArray[i] CGPointValue];
+            CGPoint p2 = [linePointsArray[i + 1] CGPointValue];
+
+            float distanceToP1 = (float) fabs(hypot(touchPoint.x - p1.x, touchPoint.y - p1.y));
+            float distanceToP2 = (float) hypot(touchPoint.x - p2.x, touchPoint.y - p2.y);
+
+            float distance = MIN(distanceToP1, distanceToP2);
+
+            if (distance <= 10.0) {
+                [_delegate userClickedOnLineKeyPoint:touchPoint
+                                           lineIndex:p
+                                          pointIndex:(distance == distanceToP2 ? i + 1 : i)];
+
+                return;
+            }
+        }
+    }
+}
+
+#pragma mark - Draw Chart
+
+- (void)populateChartLines {
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        NSArray<UIBezierPath *> *progressLines = self.chartPath[lineIndex];
+        // each chart line can be divided into multiple paths because
+        // we need ot draw each path with different color
+        // if there is not rangeColors then there is only one progressLinePath per chart
+        NSArray<UIColor *> *progressLineColors = self.progressLinePathsColors[lineIndex];
+        [self.chartLineArray[lineIndex] removeAllObjects];
+        NSUInteger progressLineIndex = 0;;
+        for (UIBezierPath *progressLinePath in progressLines) {
+            PNLineChartData *chartData = self.chartData[lineIndex];
+            CAShapeLayer *chartLine = [CAShapeLayer layer];
+            chartLine.lineCap = kCALineCapButt;
+            chartLine.lineJoin = kCALineJoinMiter;
+            chartLine.fillColor = self.backgroundColor.CGColor;
+            chartLine.lineWidth = chartData.lineWidth;
+            chartLine.path = progressLinePath.CGPath;
+            chartLine.strokeEnd = 0.0;
+            chartLine.strokeColor = progressLineColors[progressLineIndex].CGColor;
+            [self.layer addSublayer:chartLine];
+            [self.chartLineArray[lineIndex] addObject:chartLine];
+            progressLineIndex++;
+        }
+    }
+}
+
+/*
+ * strokeChart should remove the previously drawn chart lines and points
+ * and then proceed to draw the new lines
+ */
+- (void)strokeChart {
+    [self removeLayers];
+    // remove all shape layers before adding new ones
+    [self recreatePointLayers];
+    // Cavan height and width needs to be set before
+    // setNeedsDisplay is invoked because setNeedsDisplay
+    // will invoke drawRect and if Cavan dimensions is not
+    // set the chart will be misplaced
+    [self resetCavanHeight];
+    [self prepareYLabelsWithData:_chartData];
+
+    _chartPath = [[NSMutableArray alloc] init];
+    _pointPath = [[NSMutableArray alloc] init];
+    _gradeStringPaths = [NSMutableArray array];
+    _progressLinePathsColors = [[NSMutableArray alloc] init];
+
+    [self calculateChartPath:_chartPath
+               andPointsPath:_pointPath
+            andPathKeyPoints:_pathPoints
+       andPathStartEndPoints:_endPointsOfPath
+  andProgressLinePathsColors:_progressLinePathsColors];
+    [self populateChartLines];
+    // Draw each line
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        PNLineChartData *chartData = self.chartData[lineIndex];
+        NSArray<CAShapeLayer *> *chartLines =self.chartLineArray[lineIndex];
+        CAShapeLayer *pointLayer = (CAShapeLayer *) self.chartPointArray[lineIndex];
+        UIGraphicsBeginImageContext(self.frame.size);
+        if (chartData.inflexionPointColor) {
+            pointLayer.strokeColor = [[chartData.inflexionPointColor
+                    colorWithAlphaComponent:chartData.alpha] CGColor];
+        } else {
+            pointLayer.strokeColor = [PNGreen CGColor];
+        }
+        // setup the color of the chart line
+        NSArray<UIBezierPath *> *progressLines = _chartPath[lineIndex];
+        UIBezierPath *pointPath = _pointPath[lineIndex];
+
+        pointLayer.path = pointPath.CGPath;
+
+        [CATransaction begin];
+        for (NSUInteger index = 0; index < progressLines.count; index++) {
+            CAShapeLayer *chartLine = chartLines[index];
+            //chartLine strokeColor is already set. no need to override here
+            [chartLine addAnimation:self.pathAnimation forKey:@"strokeEndAnimation"];
+            chartLine.strokeEnd = 1.0;
+        }
+
+        // if you want cancel the point animation, comment this code, the point will show immediately
+        if (chartData.inflexionPointStyle != PNLineChartPointStyleNone) {
+            [pointLayer addAnimation:self.pathAnimation forKey:@"strokeEndAnimation"];
+        }
+
+        [CATransaction commit];
+
+        NSMutableArray *textLayerArray = self.gradeStringPaths[lineIndex];
+        for (CATextLayer *textLayer in textLayerArray) {
+            CABasicAnimation *fadeAnimation = [self fadeAnimation];
+            [textLayer addAnimation:fadeAnimation forKey:nil];
+        }
+
+        UIGraphicsEndImageContext();
+    }
+    [self setNeedsDisplay];
+}
+
+
+- (void)calculateChartPath:(NSMutableArray *)chartPath
+             andPointsPath:(NSMutableArray *)pointsPath
+          andPathKeyPoints:(NSMutableArray *)pathPoints
+     andPathStartEndPoints:(NSMutableArray *)pointsOfPath
+andProgressLinePathsColors:(NSMutableArray *)progressLinePathsColors {
+
+    // Draw each line
+
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+        PNLineChartData *chartData = self.chartData[lineIndex];
+
+        CGFloat yValue;
+        NSMutableArray<UIBezierPath *> *progressLines = [NSMutableArray new];
+        NSMutableArray<UIColor *> *progressLineColors = [NSMutableArray new];
+
+        UIBezierPath *pointPath = [UIBezierPath bezierPath];
+
+
+        [chartPath insertObject:progressLines atIndex:lineIndex];
+        [pointsPath insertObject:pointPath atIndex:lineIndex];
+        [progressLinePathsColors insertObject:progressLineColors atIndex:lineIndex];
+
+
+        NSMutableArray *gradePathArray = [NSMutableArray array];
+        [self.gradeStringPaths addObject:gradePathArray];
+
+        NSMutableArray *linePointsArray = [[NSMutableArray alloc] init];
+        NSMutableArray *lineStartEndPointsArray = [[NSMutableArray alloc] init];
+        int last_x = 0;
+        int last_y = 0;
+        NSMutableArray<NSDictionary<NSString *, NSValue *> *> *progressLinePaths = [NSMutableArray new];
+        UIColor *defaultColor = chartData.color != nil ? chartData.color : [UIColor greenColor];
+        CGFloat inflexionWidth = chartData.inflexionPointWidth;
+
+        for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+
+            NSValue *from = nil;
+            NSValue *to = nil;
+
+            yValue = chartData.getData(i).y;
+
+            int x = (int) (i * _xLabelWidth + _chartMarginLeft + _xLabelWidth / 2.0);
+            int y = (int)[self yValuePositionInLineChart:yValue];
+
+            // Circular point
+            if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle) {
+
+                CGRect circleRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+                CGPoint circleCenter = CGPointMake(circleRect.origin.x + (circleRect.size.width / 2), circleRect.origin.y + (circleRect.size.height / 2));
+
+                [pointPath moveToPoint:CGPointMake(circleCenter.x + (inflexionWidth / 2), circleCenter.y)];
+                [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:(CGFloat) (2 * M_PI) clockwise:YES];
+
+                //jet text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:circleCenter width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+
+                    // calculate the point for line
+                    float distance = (float) sqrt(pow(x - last_x, 2) + pow(y - last_y, 2));
+                    float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2) / distance * (x - last_x);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            }
+                // Square point
+            else if (chartData.inflexionPointStyle == PNLineChartPointStyleSquare) {
+
+                CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+                CGPoint squareCenter = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y + (squareRect.size.height / 2));
+
+                [pointPath moveToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
+                [pointPath addLineToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
+                [pointPath closePath];
+
+                // text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:squareCenter width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+
+                    // calculate the point for line
+                    float distance = (float) sqrt(pow(x - last_x, 2) + pow(y - last_y, 2));
+                    float last_x1 = last_x + (inflexionWidth / 2);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            }
+                // Triangle point
+            else if (chartData.inflexionPointStyle == PNLineChartPointStyleTriangle) {
+
+                CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
+
+                CGPoint startPoint = CGPointMake(squareRect.origin.x, squareRect.origin.y + squareRect.size.height);
+                CGPoint endPoint = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y);
+                CGPoint middlePoint = CGPointMake(squareRect.origin.x + (squareRect.size.width), squareRect.origin.y + squareRect.size.height);
+
+                [pointPath moveToPoint:startPoint];
+                [pointPath addLineToPoint:middlePoint];
+                [pointPath addLineToPoint:endPoint];
+                [pointPath closePath];
+
+                // text display text
+                if (chartData.showPointLabel) {
+                    [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:middlePoint width:inflexionWidth withChartData:chartData]];
+                }
+
+                if (i > 0) {
+                    // calculate the point for triangle
+                    float distance = (float) (sqrt(pow(x - last_x, 2) + pow(y - last_y, 2)) * 1.4);
+                    float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x);
+                    float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
+                    float x1 = x - (inflexionWidth / 2) / distance * (x - last_x);
+                    float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x1, y1)];
+                }
+            } else {
+
+                if (i > 0) {
+                    from = [NSValue valueWithCGPoint:CGPointMake(last_x, last_y)];
+                    to = [NSValue valueWithCGPoint:CGPointMake(x, y)];
+                }
+            }
+            if(from != nil && to != nil) {
+                [progressLinePaths addObject:@{@"from": from,  @"to":to}];
+                [lineStartEndPointsArray addObject:from];
+                [lineStartEndPointsArray addObject:to];
+            }
+            [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];
+            last_x = x;
+            last_y = y;
+        }
+
+        [pointsOfPath addObject:[lineStartEndPointsArray copy]];
+        [pathPoints addObject:[linePointsArray copy]];
+        // if rangeColors is not nil then it means we need to draw the chart
+        // with different colors. colorRangesBetweenP1.. function takes care of
+        // partitioning the p1->p2 into segments from which we can create UIBezierPath
+        if (self.showSmoothLines && chartData.itemCount >= 4) {
+            for (NSDictionary<NSString *, NSValue *> *item in progressLinePaths) {
+                NSArray<NSDictionary *> *calculatedRanges =
+                        [self colorRangesBetweenP1:[item[@"from"] CGPointValue]
+                                                P2:[item[@"to"] CGPointValue]
+                                       rangeColors:chartData.rangeColors
+                                      defaultColor:defaultColor];
+                for (NSDictionary *range in calculatedRanges) {
+//                    NSLog(@"range : %@ range: %@ color %@", range[@"from"], range[@"to"], range[@"color"]);
+                    UIBezierPath *currentProgressLine = [UIBezierPath bezierPath];
+                    CGPoint segmentP1 = [range[@"from"] CGPointValue];
+                    CGPoint segmentP2 = [range[@"to"] CGPointValue];
+                    [currentProgressLine moveToPoint:segmentP1];
+                    CGPoint midPoint = [PNLineChart midPointBetweenPoint1:segmentP1 andPoint2:segmentP2];
+                    [currentProgressLine addQuadCurveToPoint:midPoint
+                                                controlPoint:[PNLineChart controlPointBetweenPoint1:midPoint andPoint2:segmentP1]];
+                    [currentProgressLine addQuadCurveToPoint:segmentP2
+                                                controlPoint:[PNLineChart controlPointBetweenPoint1:midPoint andPoint2:segmentP2]];
+                    [progressLines addObject:currentProgressLine];
+                    [progressLineColors addObject:range[@"color"]];
+                }
+            }
+        } else {
+            for (NSDictionary<NSString *, NSValue *> *item in progressLinePaths) {
+                NSArray<NSDictionary *> *calculatedRanges =
+                        [self colorRangesBetweenP1:[item[@"from"] CGPointValue]
+                                                P2:[item[@"to"] CGPointValue]
+                                       rangeColors:chartData.rangeColors
+                                      defaultColor:defaultColor];
+                for (NSDictionary *range in calculatedRanges) {
+//                    NSLog(@"range : %@ range: %@ color %@", range[@"from"], range[@"to"], range[@"color"]);
+                    UIBezierPath *currentProgressLine = [UIBezierPath bezierPath];
+                    [currentProgressLine moveToPoint:[range[@"from"] CGPointValue]];
+                    [currentProgressLine addLineToPoint:[range[@"to"] CGPointValue]];
+                    [progressLines addObject:currentProgressLine];
+                    [progressLineColors addObject:range[@"color"]];
+                }
+            }
+        }
+    }
+}
+
+#pragma mark - Set Chart Data
+
+- (void)setChartData:(NSArray *)data {
+    if (data != _chartData) {
+        _chartData = data;
+    }
+}
+
+
+- (void)removeLayers {
+    for (NSArray<CALayer *> *layers in self.chartLineArray) {
+        for (CALayer *layer in layers) {
+            [layer removeFromSuperlayer];
+        }
+    }
+    for (CALayer *layer in self.chartPointArray) {
+        [layer removeFromSuperlayer];
+    }
+    self.chartLineArray = [NSMutableArray arrayWithCapacity:_chartData.count];
+    self.chartPointArray = [NSMutableArray arrayWithCapacity:_chartData.count];
+}
+
+-(void) resetCavanHeight {
+    _chartCavanHeight = self.frame.size.height - _chartMarginBottom - _chartMarginTop;
+    if (!_showLabel) {
+        _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight;
+        _chartCavanWidth = self.frame.size.width;
+        //_chartMargin = chartData.inflexionPointWidth;
+        _xLabelWidth = (_chartCavanWidth / ([_xLabels count]));
+    }
+}
+
+- (void)recreatePointLayers {
+    for (PNLineChartData *chartData in _chartData) {
+        // create as many chart line layers as there are data-lines
+        [self.chartLineArray addObject:[NSMutableArray new]];
+
+        // create point
+        CAShapeLayer *pointLayer = [CAShapeLayer layer];
+        pointLayer.strokeColor = [[chartData.color colorWithAlphaComponent:chartData.alpha] CGColor];
+        pointLayer.lineCap = kCALineCapRound;
+        pointLayer.lineJoin = kCALineJoinBevel;
+        pointLayer.fillColor = nil;
+        pointLayer.lineWidth = chartData.lineWidth;
+        [self.layer addSublayer:pointLayer];
+        [self.chartPointArray addObject:pointLayer];
+    }
+}
+
+- (void)prepareYLabelsWithData:(NSArray *)data {
+    CGFloat yMax = 0.0f;
+    CGFloat yMin = MAXFLOAT;
+    NSMutableArray *yLabelsArray = [NSMutableArray new];
+
+    for (PNLineChartData *chartData in data) {
+        // create as many chart line layers as there are data-lines
+
+        for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+            CGFloat yValue = chartData.getData(i).y;
+            [yLabelsArray addObject:[NSString stringWithFormat:@"%2f", yValue]];
+            yMax = fmaxf(yMax, yValue);
+            yMin = fminf(yMin, yValue);
+        }
+    }
+
+
+    if (_yValueMin == -FLT_MAX) {
+        _yValueMin = (_yFixedValueMin > -FLT_MAX) ? _yFixedValueMin : yMin;
+    }
+    if (_yValueMax == -FLT_MAX) {
+        _yValueMax = (CGFloat) ((_yFixedValueMax > -FLT_MAX) ? _yFixedValueMax : yMax + yMax / 10.0);
+    }
+
+    if (_showGenYLabels) {
+        [self setYLabels];
+    }
+
+}
+
+#pragma mark - Update Chart Data
+
+- (void)updateChartData:(NSArray *)data {
+    _chartData = data;
+
+    [self prepareYLabelsWithData:data];
+
+    [self calculateChartPath:_chartPath
+               andPointsPath:_pointPath
+            andPathKeyPoints:_pathPoints
+       andPathStartEndPoints:_endPointsOfPath
+  andProgressLinePathsColors:_progressLinePathsColors];
+
+    for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
+
+        CAShapeLayer *chartLine = (CAShapeLayer *) self.chartLineArray[lineIndex];
+        CAShapeLayer *pointLayer = (CAShapeLayer *) self.chartPointArray[lineIndex];
+
+
+        NSArray<UIBezierPath *> *progressLines = _chartPath[lineIndex];
+        UIBezierPath *pointPath = _pointPath[lineIndex];
+
+        for(UIBezierPath *progressLine in progressLines) {
+            CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+            pathAnimation.fromValue = (id) chartLine.path;
+            pathAnimation.toValue = (__bridge id) [progressLine CGPath];
+            pathAnimation.duration = 0.5f;
+            pathAnimation.autoreverses = NO;
+            pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+            [chartLine addAnimation:pathAnimation forKey:@"animationKey"];
+            chartLine.path = progressLine.CGPath;
+        }
+
+        CABasicAnimation *pointPathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
+        pointPathAnimation.fromValue = (id) pointLayer.path;
+        pointPathAnimation.toValue = (__bridge id) [pointPath CGPath];
+        pointPathAnimation.duration = 0.5f;
+        pointPathAnimation.autoreverses = NO;
+        pointPathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        [pointLayer addAnimation:pointPathAnimation forKey:@"animationKey"];
+
+        pointLayer.path = pointPath.CGPath;
+
+
+    }
+
+}
+
+#define IOS7_OR_LATER [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0
+
+- (void)drawRect:(CGRect)rect {
+    if (self.isShowCoordinateAxis) {
+        CGFloat yAxisOffset = 10.f;
+
+        CGContextRef ctx = UIGraphicsGetCurrentContext();
+        UIGraphicsPopContext();
+        UIGraphicsPushContext(ctx);
+        CGContextSetLineWidth(ctx, self.axisWidth);
+        CGContextSetStrokeColorWithColor(ctx, [self.axisColor CGColor]);
+
+        CGFloat xAxisWidth = CGRectGetWidth(rect) - (_chartMarginLeft + _chartMarginRight) / 2;
+        CGFloat yAxisHeight = _chartMarginBottom + _chartCavanHeight;
+
+        // draw coordinate axis
+        CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset, 0);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, yAxisHeight);
+        CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight);
+        CGContextStrokePath(ctx);
+
+        // draw y axis arrow
+        CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset - 3, 6);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, 0);
+        CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset + 3, 6);
+        CGContextStrokePath(ctx);
+
+        // draw x axis arrow
+        CGContextMoveToPoint(ctx, xAxisWidth - 6, yAxisHeight - 3);
+        CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight);
+        CGContextAddLineToPoint(ctx, xAxisWidth - 6, yAxisHeight + 3);
+        CGContextStrokePath(ctx);
+
+        if (self.showLabel) {
+
+            // draw x axis separator
+            CGPoint point;
+            for (NSUInteger i = 0; i < [self.xLabels count]; i++) {
+                point = CGPointMake(2 * _chartMarginLeft + (i * _xLabelWidth), _chartMarginBottom + _chartCavanHeight);
+                CGContextMoveToPoint(ctx, point.x, point.y - 2);
+                CGContextAddLineToPoint(ctx, point.x, point.y);
+                CGContextStrokePath(ctx);
+            }
+
+            // draw y axis separator
+            CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+            for (NSUInteger i = 0; i < [self.xLabels count]; i++) {
+                point = CGPointMake(_chartMarginBottom + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2));
+                CGContextMoveToPoint(ctx, point.x, point.y);
+                CGContextAddLineToPoint(ctx, point.x + 2, point.y);
+                CGContextStrokePath(ctx);
+            }
+        }
+
+        UIFont *font = [UIFont systemFontOfSize:11];
+
+        // draw y unit
+        if ([self.yUnit length]) {
+            CGFloat height = [PNLineChart sizeOfString:self.yUnit withWidth:30.f font:font].height;
+            CGRect drawRect = CGRectMake(_chartMarginLeft + 10 + 5, 0, 30.f, height);
+            [self drawTextInContext:ctx text:self.yUnit inRect:drawRect font:font color:self.yLabelColor];
+        }
+
+        // draw x unit
+        if ([self.xUnit length]) {
+            CGFloat height = [PNLineChart sizeOfString:self.xUnit withWidth:30.f font:font].height;
+            CGRect drawRect = CGRectMake(CGRectGetWidth(rect) - _chartMarginLeft + 5, _chartMarginBottom + _chartCavanHeight - height / 2, 25.f, height);
+            [self drawTextInContext:ctx text:self.xUnit inRect:drawRect font:font color:self.xLabelColor];
+        }
+    }
+    if (self.showYGridLines) {
+        CGContextRef ctx = UIGraphicsGetCurrentContext();
+        CGFloat yAxisOffset = _showLabel ? 10.f : 0.0f;
+        CGPoint point;
+        CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
+        if (self.yGridLinesColor) {
+            CGContextSetStrokeColorWithColor(ctx, self.yGridLinesColor.CGColor);
+        } else {
+            CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);
+        }
+        for (NSUInteger i = 0; i < _yLabelNum; i++) {
+            point = CGPointMake(_chartMarginLeft + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2));
+            CGContextMoveToPoint(ctx, point.x, point.y);
+            // add dotted style grid
+            CGFloat dash[] = {6, 5};
+            // dot diameter is 20 points
+            CGContextSetLineWidth(ctx, 0.5);
+            CGContextSetLineCap(ctx, kCGLineCapRound);
+            CGContextSetLineDash(ctx, 0.0, dash, 2);
+            CGContextAddLineToPoint(ctx, CGRectGetWidth(rect) - _chartMarginLeft + 5, point.y);
+            CGContextStrokePath(ctx);
+        }
+    }
+
+    [super drawRect:rect];
+}
+
+#pragma mark private methods
+
+/*
+ * helper function that maps a y value ( from chartData) to
+ * a position in the chart ( between _yValueMin and _yValueMax)
+ */
+- (CGFloat)yValuePositionInLineChart:(CGFloat)y {
+    CGFloat innerGrade;
+    if (!(_yValueMax - _yValueMin)) {
+        innerGrade = 0.5;
+    } else {
+        innerGrade = ((CGFloat) y - _yValueMin) / (_yValueMax - _yValueMin);
+    }
+    return _chartCavanHeight - (innerGrade * _chartCavanHeight) - (_yLabelHeight / 2) + _chartMarginTop;
+}
+
+/**
+ * return array of segments which represents the color and path
+ * for each segments.
+ * for instance if p1.y=1 and p2.y=10
+ * and rangeColor = use blue for 2<y<3 and red for 4<y<6
+ * then this function divides the space between p1 and p2 into three segments
+ *  segment #1 : 1-2 : default color
+ *  segment #2 : 2-3 : blue
+ *  segment #3 : 3-4 : default color
+ *  segment #4 : 4-6 : red
+ *  segment #5: 6-10 : default color
+ *
+ *  keep in mind that the rangeColors values are based on the chartData so it needs to
+ *  convert those values to coordinates which are valid between yValueMin and yValueMax
+ *
+ *  in order to find whether there is an overlap between any of the rangeColors and the
+ *  p1-p2 it uses NSIntersectionRange to intersect their yValues.
+ *
+ * @param p1
+ * @param p2
+ * @param rangeColors
+ * @param defaultColor
+ * @return
+ */
+- (NSArray *)colorRangesBetweenP1:(CGPoint)p1 P2:(CGPoint)p2
+                      rangeColors:(NSArray<PNLineChartColorRange *> *)rangeColors
+                     defaultColor:(UIColor *)defaultColor {
+    if (rangeColors && rangeColors.count > 0 && p2.x > p1.x) {
+        PNLineChartColorRange *colorForRangeInfo = [[rangeColors firstObject] copy];
+        NSArray *remainingRanges = nil;
+        if (rangeColors.count > 1) {
+            remainingRanges = [rangeColors subarrayWithRange:NSMakeRange(1, rangeColors.count - 1)];
+        }
+        // tRange : convert the rangeColors.range values to value between yValueMin and yValueMax
+        CGFloat transformedStart = [self yValuePositionInLineChart:(CGFloat)
+                colorForRangeInfo.range.location];
+        CGFloat transformedEnd = [self yValuePositionInLineChart:(CGFloat)
+                (colorForRangeInfo.range.location + colorForRangeInfo.range.length)];
+
+        NSRange pathRange = NSMakeRange((NSUInteger) fmin(p1.y, p2.y), (NSUInteger) fabs(p2.y - p1.y));
+        NSRange tRange = NSMakeRange((NSUInteger) fmin(transformedStart, transformedEnd),
+                (NSUInteger) fabs(transformedEnd - transformedStart));
+        if (NSIntersectionRange(tRange, pathRange).length > 0) {
+            CGPoint partition1EndPoint;
+            CGPoint partition2EndPoint;
+            NSArray *partition1 = @[];
+            NSDictionary *partition2 = nil;
+            NSArray *partition3 = @[];
+            if (p2.y >= p1.y) {
+                partition1EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmax(p1.y, tRange.location)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmax(p1.y, tRange.location));
+                partition2EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmin(p2.y, tRange.location + tRange.length)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmin(p2.y, tRange.location + tRange.length));
+            } else {
+                partition1EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmin(p1.y, tRange.location + tRange.length)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmin(p1.y, tRange.location + tRange.length));
+                partition2EndPoint = CGPointMake([PNLineChart xOfY:(CGFloat) fmax(p2.y, tRange.location)
+                                                     betweenPoint1:p1
+                                                         andPoint2:p2], (CGFloat) fmax(p2.y, tRange.location));
+            }
+            if (p1.y != partition1EndPoint.y) {
+                partition1 = [self colorRangesBetweenP1:p1
+                                                     P2:partition1EndPoint
+                                            rangeColors:remainingRanges
+                                           defaultColor:defaultColor];
+            }
+            partition2 = @{
+                    @"color": colorForRangeInfo.color,
+                    @"from": [NSValue valueWithCGPoint:partition1EndPoint],
+                    @"to": [NSValue valueWithCGPoint:partition2EndPoint]};
+            if (p2.y != partition2EndPoint.y) {
+                partition3 = [self colorRangesBetweenP1:partition2EndPoint
+                                                     P2:p2
+                                            rangeColors:remainingRanges
+                                           defaultColor:defaultColor];
+            }
+            return [[partition1 arrayByAddingObject:partition2] arrayByAddingObjectsFromArray:partition3];
+        } else {
+
+            return [self colorRangesBetweenP1:p1
+                                           P2:p2
+                                  rangeColors:remainingRanges
+                                 defaultColor:defaultColor];
+        }
+    } else {
+        return @[@{
+                @"color": defaultColor,
+                @"from": [NSValue valueWithCGPoint:p1],
+                @"to": [NSValue valueWithCGPoint:p2]}];
+    }
+}
+
+
+- (void)setupDefaultValues {
+    [super setupDefaultValues];
+    // Initialization code
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds = YES;
+    self.chartLineArray = [NSMutableArray new];
+    _showLabel = YES;
+    _showGenYLabels = YES;
+    _pathPoints = [[NSMutableArray alloc] init];
+    _endPointsOfPath = [[NSMutableArray alloc] init];
+    self.userInteractionEnabled = YES;
+
+    _yFixedValueMin = -FLT_MAX;
+    _yFixedValueMax = -FLT_MAX;
+    _yValueMax = -FLT_MAX;
+    _yValueMin = -FLT_MAX;
+    _yLabelNum = 5;
+    _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize];
+
+//    _chartMargin = 40;
+
+    _chartMarginLeft = 25.0;
+    _chartMarginRight = 25.0;
+    _chartMarginTop = 25.0;
+    _chartMarginBottom = 25.0;
+
+    _yLabelFormat = @"%1.f";
+
+    _chartCavanWidth = self.frame.size.width - _chartMarginLeft - _chartMarginRight;
+    _chartCavanHeight = self.frame.size.height - _chartMarginBottom - _chartMarginTop;
+
+    // Coordinate Axis Default Values
+    _showCoordinateAxis = NO;
+    _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f];
+    _axisWidth = 1.f;
+
+    // do not create curved line chart by default
+    _showSmoothLines = NO;
+
+}
+
+#pragma mark - tools
+
++ (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font {
+    CGSize size = CGSizeMake(width, MAXFLOAT);
+
+    if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
+        NSDictionary *tdic = @{NSFontAttributeName: font};
+        size = [text boundingRectWithSize:size
+                                  options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
+                               attributes:tdic
+                                  context:nil].size;
+    } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        size = [text sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByCharWrapping];
+#pragma clang diagnostic pop
+    }
+
+    return size;
+}
+
++ (CGPoint)midPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    return CGPointMake((point1.x + point2.x) / 2, (point1.y + point2.y) / 2);
+}
+
++ (CGFloat)xOfY:(CGFloat)y betweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    CGFloat m = (point2.y - point1.y) / (point2.x - point1.x);
+    // formulate = y - y1 = m (x - x1) = mx - mx1 -> mx = y - y1 + mx1 ->
+    // x = (y - y1 + mx1) / m
+    return (y - point1.y + m * point1.x) / m;
+}
+
+
++ (CGPoint)controlPointBetweenPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2 {
+    CGPoint controlPoint = [self midPointBetweenPoint1:point1 andPoint2:point2];
+    CGFloat diffY = abs((int) (point2.y - controlPoint.y));
+    if (point1.y < point2.y)
+        controlPoint.y += diffY;
+    else if (point1.y > point2.y)
+        controlPoint.y -= diffY;
+    return controlPoint;
+}
+
+- (void)drawTextInContext:(CGContextRef)ctx text:(NSString *)text inRect:(CGRect)rect font:(UIFont *)font color:(UIColor *)color {
+    if (IOS7_OR_LATER) {
+        NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+        priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
+        priceParagraphStyle.alignment = NSTextAlignmentLeft;
+
+        if (color != nil) {
+            [text drawInRect:rect
+              withAttributes:@{NSParagraphStyleAttributeName: priceParagraphStyle, NSFontAttributeName: font,
+                      NSForegroundColorAttributeName: color}];
+        } else {
+            [text drawInRect:rect
+              withAttributes:@{NSParagraphStyleAttributeName: priceParagraphStyle, NSFontAttributeName: font}];
+        }
+    } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        [text drawInRect:rect
+                withFont:font
+           lineBreakMode:NSLineBreakByTruncatingTail
+               alignment:NSTextAlignmentLeft];
+#pragma clang diagnostic pop
+    }
+}
+
+- (NSString *)formatYLabel:(double)value {
+
+    if (self.yLabelBlockFormatter) {
+        return self.yLabelBlockFormatter((CGFloat) value);
+    } else {
+        if (!self.thousandsSeparator) {
+            NSString *format = self.yLabelFormat ?: @"%1.f";
+            return [NSString stringWithFormat:format, value];
+        }
+
+        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
+        [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
+        [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
+        return [numberFormatter stringFromNumber:@(value)];
+    }
+}
+
+- (UIView *)getLegendWithMaxWidth:(CGFloat)mWidth {
+    if ([self.chartData count] < 1) {
+        return nil;
+    }
+
+    /* This is a short line that refers to the chart data */
+    CGFloat legendLineWidth = 40;
+
+    /* x and y are the coordinates of the starting point of each legend item */
+    CGFloat x = 0;
+    CGFloat y = 0;
+
+    /* accumulated height */
+    CGFloat totalHeight = 0;
+    CGFloat totalWidth = 0;
+
+    NSMutableArray *legendViews = [[NSMutableArray alloc] init];
+
+    /* Determine the max width of each legend item */
+    CGFloat maxLabelWidth;
+    if (self.legendStyle == PNLegendItemStyleStacked) {
+        maxLabelWidth = mWidth - legendLineWidth;
+    } else {
+        maxLabelWidth = MAXFLOAT;
+    }
+
+    /* this is used when labels wrap text and the line
+     * should be in the middle of the first row */
+    CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test"
+                                              withWidth:MAXFLOAT
+                                                   font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height;
+
+    NSUInteger counter = 0;
+    NSUInteger rowWidth = 0;
+    NSUInteger rowMaxHeight = 0;
+
+    for (PNLineChartData *pdata in self.chartData) {
+        /* Expected label size*/
+        CGSize labelsize = [PNLineChart sizeOfString:pdata.dataTitle
+                                           withWidth:maxLabelWidth
+                                                font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]];
+
+        /* draw lines */
+        if ((rowWidth + labelsize.width + legendLineWidth > mWidth) && (self.legendStyle == PNLegendItemStyleSerial)) {
+            rowWidth = 0;
+            x = 0;
+            y += rowMaxHeight;
+            rowMaxHeight = 0;
+        }
+        rowWidth += labelsize.width + legendLineWidth;
+        totalWidth = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(rowWidth, totalWidth) : fmaxf(totalWidth, labelsize.width + legendLineWidth);
+
+        /* If there is inflection decorator, the line is composed of two lines
+         * and this is the space that separates two lines in order to put inflection
+         * decorator */
+
+        CGFloat inflexionWidthSpacer = pdata.inflexionPointStyle == PNLineChartPointStyleTriangle ? pdata.inflexionPointWidth / 2 : pdata.inflexionPointWidth;
+
+        CGFloat halfLineLength;
+
+        if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) {
+            halfLineLength = (CGFloat) ((legendLineWidth * 0.8 - inflexionWidthSpacer) / 2);
+        } else {
+            halfLineLength = (CGFloat) (legendLineWidth * 0.8);
+        }
+
+        UIView *line = [[UIView alloc] initWithFrame:CGRectMake((CGFloat) (x + legendLineWidth * 0.1), y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)];
+
+        line.backgroundColor = pdata.color;
+        line.alpha = pdata.alpha;
+        [legendViews addObject:line];
+
+        if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) {
+            line = [[UIView alloc] initWithFrame:CGRectMake((CGFloat) (x + legendLineWidth * 0.1 + halfLineLength + inflexionWidthSpacer), y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)];
+            line.backgroundColor = pdata.color;
+            line.alpha = pdata.alpha;
+            [legendViews addObject:line];
+        }
+
+        // Add inflexion type
+        UIColor *inflexionPointColor = pdata.inflexionPointColor;
+        if (!inflexionPointColor) {
+            inflexionPointColor = pdata.color;
+        }
+        [legendViews addObject:[self drawInflexion:pdata.inflexionPointWidth
+                                            center:CGPointMake(x + legendLineWidth / 2, y + singleRowHeight / 2)
+                                       strokeWidth:pdata.lineWidth
+                                    inflexionStyle:pdata.inflexionPointStyle
+                                          andColor:inflexionPointColor
+                                          andAlpha:pdata.alpha]];
+
+        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, labelsize.width, labelsize.height)];
+        label.text = pdata.dataTitle;
+        label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor];
+        label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f];
+        label.lineBreakMode = NSLineBreakByWordWrapping;
+        label.numberOfLines = 0;
+
+        rowMaxHeight = (NSUInteger) fmaxf(rowMaxHeight, labelsize.height);
+        x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth;
+        y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0;
+
+
+        totalHeight = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height;
+
+        [legendViews addObject:label];
+        counter++;
+    }
+
+    UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, mWidth, totalHeight)];
+
+    for (UIView *v in legendViews) {
+        [legend addSubview:v];
+    }
+    return legend;
+}
+
+
+- (UIImageView *)drawInflexion:(CGFloat)size center:(CGPoint)center strokeWidth:(CGFloat)sw inflexionStyle:(PNLineChartPointStyle)type andColor:(UIColor *)color andAlpha:(CGFloat)alfa {
+    //Make the size a little bigger so it includes also border stroke
+    CGSize aSize = CGSizeMake(size + sw, size + sw);
+
+
+    UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+
+
+    if (type == PNLineChartPointStyleCircle) {
+        CGContextAddArc(context, (size + sw) / 2, (size + sw) / 2, size / 2, 0, (CGFloat) (M_PI * 2), YES);
+    } else if (type == PNLineChartPointStyleSquare) {
+        CGContextAddRect(context, CGRectMake(sw / 2, sw / 2, size, size));
+    } else if (type == PNLineChartPointStyleTriangle) {
+        CGContextMoveToPoint(context, sw / 2, size + sw / 2);
+        CGContextAddLineToPoint(context, size + sw / 2, size + sw / 2);
+        CGContextAddLineToPoint(context, size / 2 + sw / 2, sw / 2);
+        CGContextAddLineToPoint(context, sw / 2, size + sw / 2);
+        CGContextClosePath(context);
+    }
+
+    //Set some stroke properties
+    CGContextSetLineWidth(context, sw);
+    CGContextSetAlpha(context, alfa);
+    CGContextSetStrokeColorWithColor(context, color.CGColor);
+
+    //Finally draw
+    CGContextDrawPath(context, kCGPathStroke);
+
+    //now get the image from the context
+    UIImage *squareImage = UIGraphicsGetImageFromCurrentImageContext();
+
+    UIGraphicsEndImageContext();
+
+    //// Translate origin
+    CGFloat originX = (CGFloat) (center.x - (size + sw) / 2.0);
+    CGFloat originY = (CGFloat) (center.y - (size + sw) / 2.0);
+
+    UIImageView *squareImageView = [[UIImageView alloc] initWithImage:squareImage];
+    [squareImageView setFrame:CGRectMake(originX, originY, size + sw, size + sw)];
+    return squareImageView;
+}
+
+#pragma mark setter and getter
+
+- (CATextLayer *)createPointLabelFor:(CGFloat)grade pointCenter:(CGPoint)pointCenter width:(CGFloat)width withChartData:(PNLineChartData *)chartData {
+    CATextLayer *textLayer = [[CATextLayer alloc] init];
+    [textLayer setAlignmentMode:kCAAlignmentCenter];
+    [textLayer setForegroundColor:[chartData.pointLabelColor CGColor]];
+    [textLayer setBackgroundColor:self.backgroundColor.CGColor];
+//    [textLayer setBackgroundColor:[self.backgroundColor colorWithAlphaComponent:0.8].CGColor];
+//    [textLayer setCornerRadius:(CGFloat) (textLayer.fontSize / 8.0)];
+
+    if (chartData.pointLabelFont != nil) {
+        [textLayer setFont:(__bridge CFTypeRef) (chartData.pointLabelFont)];
+        textLayer.fontSize = [chartData.pointLabelFont pointSize];
+    }
+
+    CGFloat textHeight = (CGFloat) (textLayer.fontSize * 1.1);
+    // FIXME: convert the grade to string and use its length instead of hardcoding 8
+    CGFloat textWidth = width * 8;
+    CGFloat textStartPosY;
+
+    textStartPosY = pointCenter.y - textLayer.fontSize;
+
+    [self.layer addSublayer:textLayer];
+
+    if (chartData.pointLabelFormat != nil) {
+        [textLayer setString:[[NSString alloc] initWithFormat:chartData.pointLabelFormat, grade]];
+    } else {
+        [textLayer setString:[[NSString alloc] initWithFormat:_yLabelFormat, grade]];
+    }
+
+    [textLayer setFrame:CGRectMake(0, 0, textWidth, textHeight)];
+    [textLayer setPosition:CGPointMake(pointCenter.x, textStartPosY)];
+    textLayer.contentsScale = [UIScreen mainScreen].scale;
+
+    return textLayer;
+}
+
+- (CABasicAnimation *)fadeAnimation {
+    CABasicAnimation *fadeAnimation = nil;
+    if (self.displayAnimated) {
+        fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        fadeAnimation.fromValue = @0.0F;
+        fadeAnimation.toValue = @1.0F;
+        fadeAnimation.duration = 2.0;
+    }
+    return fadeAnimation;
+}
+
+- (CABasicAnimation *)pathAnimation {
+    if (self.displayAnimated && !_pathAnimation) {
+        _pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        _pathAnimation.duration = 1.0;
+        _pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        _pathAnimation.fromValue = @0.0f;
+        _pathAnimation.toValue = @1.0f;
+    }
+    if(!self.displayAnimated) {
+        _pathAnimation = nil;
+    }
+    return _pathAnimation;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.h b/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.h
new file mode 100755
index 0000000..2158e8e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.h
@@ -0,0 +1,61 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNLineChartPointStyle) {
+    PNLineChartPointStyleNone = 0,
+    PNLineChartPointStyleCircle = 1,
+    PNLineChartPointStyleSquare = 3,
+    PNLineChartPointStyleTriangle = 4
+};
+
+@class PNLineChartDataItem;
+
+typedef PNLineChartDataItem *(^LCLineChartDataGetter)(NSUInteger item);
+
+@interface PNLineChartColorRange : NSObject<NSCopying>
+
+@property(nonatomic) NSRange range;
+@property(nonatomic) BOOL inclusive;
+@property(nonatomic, retain) UIColor *color;
+
+- (id)initWithRange:(NSRange)range color:(UIColor *)color;
+
+@end
+
+@interface PNLineChartData : NSObject
+
+@property (strong) UIColor *color;
+@property (nonatomic) CGFloat alpha;
+@property NSUInteger itemCount;
+@property (copy) LCLineChartDataGetter getData;
+@property (strong, nonatomic) NSString *dataTitle;
+
+@property (nonatomic) BOOL showPointLabel;
+@property (nonatomic) UIColor *pointLabelColor;
+@property (nonatomic) UIFont *pointLabelFont;
+@property (nonatomic) NSString *pointLabelFormat;
+
+@property (nonatomic, assign) PNLineChartPointStyle inflexionPointStyle;
+@property (nonatomic) UIColor *inflexionPointColor;
+
+/**
+ * if rangeColor is set and the lineChartData values are within any
+ * of the given range then use the rangeColor.color otherwise use
+ * self.color for the rest of the graph
+ */
+@property(strong) NSArray<PNLineChartColorRange *> *rangeColors;
+
+/**
+ * If PNLineChartPointStyle is circle, this returns the circle's diameter.
+ * If PNLineChartPointStyle is square, each point is a square with each side equal in length to this value.
+ */
+@property (nonatomic, assign) CGFloat inflexionPointWidth;
+
+@property (nonatomic, assign) CGFloat lineWidth;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.m b/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.m
new file mode 100755
index 0000000..bbf2647
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChartData.m
@@ -0,0 +1,54 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import "PNLineChartData.h"
+
+
+@implementation PNLineChartColorRange
+
+- (id)initWithRange:(NSRange)range color:(UIColor *)color {
+    self = [super init];
+    if (self) {
+        self.range = range;
+        self.color = color;
+    }
+    return self;
+}
+
+
+- (id)copyWithZone:(NSZone *)zone {
+    PNLineChartColorRange *copy = [[self class] allocWithZone:zone];
+    copy.color = self.color;
+    copy.range = self.range;
+    return copy;
+}
+
+@end
+
+@implementation PNLineChartData
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        [self setupDefaultValues];
+    }
+    
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    _inflexionPointStyle = PNLineChartPointStyleNone;
+    _inflexionPointWidth = 6.f;
+    _lineWidth = 2.f;
+    _alpha = 1.f;
+    _showPointLabel = NO;
+    _pointLabelColor = [UIColor blackColor];
+    _pointLabelFormat = @"%1.f";
+    _rangeColors = nil;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.h b/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.h
new file mode 100755
index 0000000..ad2d23d
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.h
@@ -0,0 +1,17 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNLineChartDataItem : NSObject
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y;
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY;
+
+@property (readonly) CGFloat y; // should be within the y range
+@property (readonly) CGFloat rawY; // this is the raw value, used for point label.
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.m b/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.m
new file mode 100755
index 0000000..1beea91
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNLineChartDataItem.m
@@ -0,0 +1,38 @@
+//
+// Created by J��rg Polakowski on 14/12/13.
+// Copyright (c) 2013 kevinzhow. All rights reserved.
+//
+
+#import "PNLineChartDataItem.h"
+
+@interface PNLineChartDataItem ()
+
+- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY;
+
+@property (readwrite) CGFloat y;    // should be within the y range
+@property (readwrite) CGFloat rawY; // this is the raw value, used for point label.
+
+@end
+
+@implementation PNLineChartDataItem
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y
+{
+    return [[PNLineChartDataItem alloc] initWithY:y andRawY:y];
+}
+
++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY {
+    return [[PNLineChartDataItem alloc] initWithY:y andRawY:rawY];
+}
+
+- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY
+{
+    if ((self = [super init])) {
+        self.y = y;
+        self.rawY = rawY;
+    }
+
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNPieChart.h b/PNChartdemo/PNChartdemo/PNChart/PNPieChart.h
new file mode 100755
index 0000000..204afb5
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNPieChart.h
@@ -0,0 +1,68 @@
+//
+//  PNPieChart.h
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNPieChartDataItem.h"
+#import "PNGenericChart.h"
+#import "PNChartDelegate.h"
+
+@interface PNPieChart : PNGenericChart
+
+- (id)initWithFrame:(CGRect)frame items:(NSArray *)items;
+
+@property (nonatomic, readonly) NSArray	*items;
+
+/** Default is 18-point Avenir Medium. */
+@property (nonatomic) UIFont  *descriptionTextFont;
+
+/** Default is white. */
+@property (nonatomic) UIColor *descriptionTextColor;
+
+/** Default is black, with an alpha of 0.4. */
+@property (nonatomic) UIColor *descriptionTextShadowColor;
+
+/** Default is CGSizeMake(0, 1). */
+@property (nonatomic) CGSize   descriptionTextShadowOffset;
+
+/** Default is 1.0. */
+@property (nonatomic) NSTimeInterval duration;
+
+/** Show only values, this is useful when legend is present */
+@property (nonatomic) BOOL showOnlyValues;
+
+/** Show absolute values not relative i.e. percentages */
+@property (nonatomic) BOOL showAbsoluteValues;
+
+/** Hide percentage labels less than cutoff value */
+@property (nonatomic, assign) CGFloat labelPercentageCutoff;
+
+/** Default YES. */
+@property (nonatomic) BOOL shouldHighlightSectorOnTouch;
+
+/** Current outer radius. Override recompute() to change this. **/
+@property (nonatomic) CGFloat outerCircleRadius;
+
+/** Current inner radius. Override recompute() to change this. **/
+@property (nonatomic) CGFloat innerCircleRadius;
+
+@property (nonatomic, weak) id<PNChartDelegate> delegate;
+
+/** Update chart items. Does not update chart itself. */
+- (void)updateChartData:(NSArray *)data;
+
+/** Multiple selection */
+@property (nonatomic, assign) BOOL enableMultipleSelection;
+
+/** show only tiles, not values or percentage */
+@property (nonatomic) BOOL hideValues;
+
+- (void)strokeChart;
+
+- (void)recompute;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNPieChart.m b/PNChartdemo/PNChartdemo/PNChart/PNPieChart.m
new file mode 100755
index 0000000..ae9ab7a
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNPieChart.m
@@ -0,0 +1,508 @@
+//
+//  PNPieChart.m
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import "PNPieChart.h"
+//needed for the expected label size
+#import "PNLineChart.h"
+
+@interface PNPieChart()
+
+@property (nonatomic) NSArray *items;
+@property (nonatomic) NSArray *endPercentages;
+
+@property (nonatomic) UIView         *contentView;
+@property (nonatomic) CAShapeLayer   *pieLayer;
+@property (nonatomic) NSMutableArray *descriptionLabels;
+@property (strong, nonatomic) CAShapeLayer *sectorHighlight;
+
+@property (nonatomic, strong) NSMutableDictionary *selectedItems;
+
+- (void)loadDefault;
+
+- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index;
+- (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index;
+- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index;
+- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index;
+- (CGFloat)ratioForItemAtIndex:(NSUInteger)index;
+
+- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
+                               borderWidth:(CGFloat)borderWidth
+                                 fillColor:(UIColor *)fillColor
+                               borderColor:(UIColor *)borderColor
+                           startPercentage:(CGFloat)startPercentage
+                             endPercentage:(CGFloat)endPercentage;
+
+
+@end
+
+
+@implementation PNPieChart
+
+-(id)initWithFrame:(CGRect)frame items:(NSArray *)items{
+    self = [self initWithFrame:frame];
+    if(self){
+        _items = [NSArray arrayWithArray:items];
+        [self baseInit];
+    }
+    
+    return self;
+}
+
+- (void)awakeFromNib{
+    [super awakeFromNib];
+    [self baseInit];
+}
+
+- (void)baseInit{
+    _selectedItems = [NSMutableDictionary dictionary];
+    //������������������,���������������������������������������������,������������������,���������������,���������������view���������,���������������������������������
+    
+    CGFloat minimal = (CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds)) ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds);
+    
+    _outerCircleRadius  = minimal / 2;
+    _innerCircleRadius  = minimal / 6;
+//    _outerCircleRadius  = CGRectGetWidth(self.bounds) / 2;
+//    _innerCircleRadius  = CGRectGetWidth(self.bounds) / 6;
+    _descriptionTextColor = [UIColor whiteColor];
+    _descriptionTextFont  = [UIFont fontWithName:@"Avenir-Medium" size:18.0];
+    _descriptionTextShadowColor  = [[UIColor blackColor] colorWithAlphaComponent:0.4];
+    _descriptionTextShadowOffset =  CGSizeMake(0, 1);
+    _duration = 1.0;
+    _shouldHighlightSectorOnTouch = YES;
+    _enableMultipleSelection = NO;
+    _hideValues = NO;
+    
+    [super setupDefaultValues];
+    [self loadDefault];
+}
+
+- (void)loadDefault{
+    __block CGFloat currentTotal = 0;
+    CGFloat total = [[self.items valueForKeyPath:@"@sum.value"] floatValue];
+    NSMutableArray *endPercentages = [NSMutableArray new];
+    [_items enumerateObjectsUsingBlock:^(PNPieChartDataItem *item, NSUInteger idx, BOOL *stop) {
+        if (total == 0){
+            [endPercentages addObject:@(1.0 / _items.count * (idx + 1))];
+        }else{
+            currentTotal += item.value;
+            [endPercentages addObject:@(currentTotal / total)];
+        }
+    }];
+    self.endPercentages = [endPercentages copy];
+    
+    [_contentView removeFromSuperview];
+    _contentView = [[UIView alloc] initWithFrame:self.bounds];
+    [self addSubview:_contentView];
+    _descriptionLabels = [NSMutableArray new];
+    
+    _pieLayer = [CAShapeLayer layer];
+    [_contentView.layer addSublayer:_pieLayer];
+
+}
+
+/** Override this to change how inner attributes are computed. **/
+- (void)recompute {
+    
+    //������
+    CGFloat minimal = (CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds)) ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds);
+    self.outerCircleRadius = minimal / 2;
+    self.innerCircleRadius = minimal / 6;
+}
+
+#pragma mark -
+
+- (void)strokeChart{
+    [self loadDefault];
+    [self recompute];
+    
+    PNPieChartDataItem *currentItem;
+    for (int i = 0; i < _items.count; i++) {
+        currentItem = [self dataItemForIndex:i];
+        
+        
+        CGFloat startPercentage = [self startPercentageForItemAtIndex:i];
+        CGFloat endPercentage   = [self endPercentageForItemAtIndex:i];
+        
+        CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+        CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
+        
+        CAShapeLayer *currentPieLayer =	[self newCircleLayerWithRadius:radius
+                                                           borderWidth:borderWidth
+                                                             fillColor:[UIColor clearColor]
+                                                           borderColor:currentItem.color
+                                                       startPercentage:startPercentage
+                                                         endPercentage:endPercentage];
+        [_pieLayer addSublayer:currentPieLayer];
+    }
+    
+    [self maskChart];
+    
+    for (int i = 0; i < _items.count; i++) {
+        UILabel *descriptionLabel =  [self descriptionLabelForItemAtIndex:i];
+        [_contentView addSubview:descriptionLabel];
+        [_descriptionLabels addObject:descriptionLabel];
+    }
+    
+    [self addAnimationIfNeeded];
+}
+
+- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index{
+    PNPieChartDataItem *currentDataItem = [self dataItemForIndex:index];
+    CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+    CGFloat centerPercentage = ([self startPercentageForItemAtIndex:index] + [self endPercentageForItemAtIndex:index])/ 2;
+    CGFloat rad = centerPercentage * 2 * M_PI;
+    
+    UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
+    NSString *titleText = currentDataItem.textDescription;
+    
+    NSString *titleValue;
+    
+    if (self.showAbsoluteValues) {
+        titleValue = [NSString stringWithFormat:@"%.0f",currentDataItem.value];
+    }else{
+        titleValue = [NSString stringWithFormat:@"%.0f%%",[self ratioForItemAtIndex:index] * 100];
+    }
+    
+    if (self.hideValues)
+        descriptionLabel.text = titleText;
+    else if(!titleText || self.showOnlyValues)
+        descriptionLabel.text = titleValue;
+    else {
+        NSString* str = [titleValue stringByAppendingString:[NSString stringWithFormat:@"\n%@",titleText]];
+        descriptionLabel.text = str ;
+    }
+    
+    //If value is less than cutoff, show no label
+    if ([self ratioForItemAtIndex:index] < self.labelPercentageCutoff )
+    {
+        descriptionLabel.text = nil;
+    }
+    
+    CGPoint center = CGPointMake(_outerCircleRadius + distance * sin(rad),
+                                 _outerCircleRadius - distance * cos(rad));
+    
+    descriptionLabel.font = _descriptionTextFont;
+    CGSize labelSize = [descriptionLabel.text sizeWithAttributes:@{NSFontAttributeName:descriptionLabel.font}];
+    descriptionLabel.frame = CGRectMake(descriptionLabel.frame.origin.x, descriptionLabel.frame.origin.y,
+                                        descriptionLabel.frame.size.width, labelSize.height);
+    descriptionLabel.numberOfLines   = 0;
+    descriptionLabel.textColor       = _descriptionTextColor;
+    descriptionLabel.shadowColor     = _descriptionTextShadowColor;
+    descriptionLabel.shadowOffset    = _descriptionTextShadowOffset;
+    descriptionLabel.textAlignment   = NSTextAlignmentCenter;
+    descriptionLabel.center          = center;
+    descriptionLabel.alpha           = 0;
+    descriptionLabel.backgroundColor = [UIColor clearColor];
+    return descriptionLabel;
+}
+
+- (void)updateChartData:(NSArray *)items {
+    self.items = items;
+}
+
+- (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index{
+    return self.items[index];
+}
+
+- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index{
+    if(index == 0){
+        return 0;
+    }
+    
+    return [_endPercentages[index - 1] floatValue];
+}
+
+- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index{
+    return [_endPercentages[index] floatValue];
+}
+
+- (CGFloat)ratioForItemAtIndex:(NSUInteger)index{
+    return [self endPercentageForItemAtIndex:index] - [self startPercentageForItemAtIndex:index];
+}
+
+#pragma mark private methods
+
+- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
+                               borderWidth:(CGFloat)borderWidth
+                                 fillColor:(UIColor *)fillColor
+                               borderColor:(UIColor *)borderColor
+                           startPercentage:(CGFloat)startPercentage
+                             endPercentage:(CGFloat)endPercentage{
+    CAShapeLayer *circle = [CAShapeLayer layer];
+    
+    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds),CGRectGetMidY(self.bounds));
+    
+    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
+                                                        radius:radius
+                                                    startAngle:-M_PI_2
+                                                      endAngle:M_PI_2 * 3
+                                                     clockwise:YES];
+    
+    circle.fillColor   = fillColor.CGColor;
+    circle.strokeColor = borderColor.CGColor;
+    circle.strokeStart = startPercentage;
+    circle.strokeEnd   = endPercentage;
+    circle.lineWidth   = borderWidth;
+    circle.path        = path.CGPath;
+    
+    return circle;
+}
+
+- (void)maskChart{
+    CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
+    CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
+    CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:radius
+                                                 borderWidth:borderWidth
+                                                   fillColor:[UIColor clearColor]
+                                                 borderColor:[UIColor blackColor]
+                                             startPercentage:0
+                                               endPercentage:1];
+    
+    _pieLayer.mask = maskLayer;
+}
+
+- (void)addAnimationIfNeeded{
+    if (self.displayAnimated) {
+        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        animation.duration  = _duration;
+        animation.fromValue = @0;
+        animation.toValue   = @1;
+        animation.delegate  = self;
+        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        animation.removedOnCompletion = YES;
+        [_pieLayer.mask addAnimation:animation forKey:@"circleAnimation"];
+    }
+    else {
+        // Add description labels since no animation is required
+        [_descriptionLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+            [obj setAlpha:1];
+        }];
+    }
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
+    [_descriptionLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        [UIView animateWithDuration:0.2 animations:^(){
+            [obj setAlpha:1];
+        }];
+    }];
+}
+
+- (void)didTouchAt:(CGPoint)touchLocation
+{
+    CGPoint circleCenter = CGPointMake(_contentView.bounds.size.width/2, _contentView.bounds.size.height/2);
+    
+    CGFloat distanceFromCenter = sqrtf(powf((touchLocation.y - circleCenter.y),2) + powf((touchLocation.x - circleCenter.x),2));
+    
+    if (distanceFromCenter < _innerCircleRadius) {
+        if ([self.delegate respondsToSelector:@selector(didUnselectPieItem)]) {
+            [self.delegate didUnselectPieItem];
+        }
+        [self.sectorHighlight removeFromSuperlayer];
+        return;
+    }
+    
+    CGFloat percentage = [self findPercentageOfAngleInCircle:circleCenter fromPoint:touchLocation];
+    int index = 0;
+    while (percentage > [self endPercentageForItemAtIndex:index]) {
+        index ++;
+    }
+    
+    if ([self.delegate respondsToSelector:@selector(userClickedOnPieIndexItem:)]) {
+        [self.delegate userClickedOnPieIndexItem:index];
+    }
+    
+    if (self.shouldHighlightSectorOnTouch)
+    {
+        if (!self.enableMultipleSelection)
+        {
+            if (self.sectorHighlight)
+                [self.sectorHighlight removeFromSuperlayer];
+        }
+        
+        PNPieChartDataItem *currentItem = [self dataItemForIndex:index];
+        
+        CGFloat red,green,blue,alpha;
+        UIColor *old = currentItem.color;
+        [old getRed:&red green:&green blue:&blue alpha:&alpha];
+        alpha /= 2;
+        UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
+        
+        CGFloat startPercentage = [self startPercentageForItemAtIndex:index];
+        CGFloat endPercentage   = [self endPercentageForItemAtIndex:index];
+        
+        self.sectorHighlight = [self newCircleLayerWithRadius:_outerCircleRadius + 5
+                                                  borderWidth:10
+                                                    fillColor:[UIColor clearColor]
+                                                  borderColor:newColor
+                                              startPercentage:startPercentage
+                                                endPercentage:endPercentage];
+        
+        if (self.enableMultipleSelection)
+        {
+            NSString *dictIndex = [NSString stringWithFormat:@"%d", index];
+            CAShapeLayer *indexShape = [self.selectedItems valueForKey:dictIndex];
+            if (indexShape)
+            {
+                [indexShape removeFromSuperlayer];
+                [self.selectedItems removeObjectForKey:dictIndex];
+            }
+            else
+            {
+                [self.selectedItems setObject:self.sectorHighlight forKey:dictIndex];
+                [_contentView.layer addSublayer:self.sectorHighlight];
+            }
+        }
+        else
+        {
+            [_contentView.layer addSublayer:self.sectorHighlight];
+        }
+    }
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:_contentView];
+        [self didTouchAt:touchLocation];
+    }
+}
+
+- (CGFloat) findPercentageOfAngleInCircle:(CGPoint)center fromPoint:(CGPoint)reference{
+    //Find angle of line Passing In Reference And Center
+    CGFloat angleOfLine = atanf((reference.y - center.y) / (reference.x - center.x));
+    CGFloat percentage = (angleOfLine + M_PI/2)/(2 * M_PI);
+    return (reference.x - center.x) > 0 ? percentage : percentage + .5;
+}
+
+- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{
+    if ([self.items count] < 1) {
+        return nil;
+    }
+    
+    /* This is a small circle that refers to the chart data */
+    CGFloat legendCircle = 16;
+    
+    CGFloat hSpacing = 0;
+    
+    CGFloat beforeLabel = legendCircle + hSpacing;
+    
+    /* x and y are the coordinates of the starting point of each legend item */
+    CGFloat x = 0;
+    CGFloat y = 0;
+    
+    /* accumulated width and height */
+    CGFloat totalWidth = 0;
+    CGFloat totalHeight = 0;
+    
+    NSMutableArray *legendViews = [[NSMutableArray alloc] init];
+    
+    /* Determine the max width of each legend item */
+    CGFloat maxLabelWidth;
+    if (self.legendStyle == PNLegendItemStyleStacked) {
+        maxLabelWidth = mWidth - beforeLabel;
+    }else{
+        maxLabelWidth = MAXFLOAT;
+    }
+    
+    /* this is used when labels wrap text and the line
+     * should be in the middle of the first row */
+    CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test"
+                                              withWidth:MAXFLOAT
+                                                   font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height;
+    
+    NSUInteger counter = 0;
+    NSUInteger rowWidth = 0;
+    NSUInteger rowMaxHeight = 0;
+    
+    for (PNPieChartDataItem *pdata in self.items) {
+        /* Expected label size*/
+        CGSize labelsize = [PNLineChart sizeOfString:pdata.textDescription
+                                           withWidth:maxLabelWidth
+                                                font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]];
+        
+        if ((rowWidth + labelsize.width + beforeLabel > mWidth)&&(self.legendStyle == PNLegendItemStyleSerial)) {
+            rowWidth = 0;
+            x = 0;
+            y += rowMaxHeight;
+            rowMaxHeight = 0;
+        }
+        rowWidth += labelsize.width + beforeLabel;
+        totalWidth = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(rowWidth, totalWidth) : fmaxf(totalWidth, labelsize.width + beforeLabel);
+        // Add inflexion type
+        [legendViews addObject:[self drawInflexion:legendCircle * .6
+                                            center:CGPointMake(x + legendCircle / 2, y + singleRowHeight / 2)
+                                          andColor:pdata.color]];
+        
+        
+        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + beforeLabel, y, labelsize.width, labelsize.height)];
+        label.text = pdata.textDescription;
+        label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor];
+        label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f];
+        label.lineBreakMode = NSLineBreakByWordWrapping;
+        label.numberOfLines = 0;
+        
+        
+        rowMaxHeight = fmaxf(rowMaxHeight, labelsize.height);
+        x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + beforeLabel;
+        y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0;
+        
+        
+        totalHeight = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height;
+        [legendViews addObject:label];
+        counter ++;
+    }
+    
+    UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, totalWidth, totalHeight)];
+    
+    for (UIView* v in legendViews) {
+        [legend addSubview:v];
+    }
+    return legend;
+}
+
+
+- (UIImageView*)drawInflexion:(CGFloat)size center:(CGPoint)center andColor:(UIColor*)color
+{
+    //Make the size a little bigger so it includes also border stroke
+    CGSize aSize = CGSizeMake(size, size);
+    
+    
+    UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    CGContextAddArc(context, size/2, size/ 2, size/2, 0, M_PI*2, YES);
+    
+    
+    //Set some fill color
+    CGContextSetFillColorWithColor(context, color.CGColor);
+    
+    //Finally draw
+    CGContextDrawPath(context, kCGPathFill);
+    
+    //now get the image from the context
+    UIImage *squareImage = UIGraphicsGetImageFromCurrentImageContext();
+    
+    UIGraphicsEndImageContext();
+    
+    //// Translate origin
+    CGFloat originX = center.x - (size) / 2.0;
+    CGFloat originY = center.y - (size) / 2.0;
+    
+    UIImageView *squareImageView = [[UIImageView alloc]initWithImage:squareImage];
+    [squareImageView setFrame:CGRectMake(originX, originY, size, size)];
+    return squareImageView;
+}
+
+/* Redraw the chart on autolayout */
+-(void)layoutSubviews {
+    [super layoutSubviews];
+    [self strokeChart];
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.h b/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.h
new file mode 100755
index 0000000..08d48e9
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.h
@@ -0,0 +1,25 @@
+//
+//  PNPieChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNPieChartDataItem : NSObject
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color;
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color
+                      description:(NSString *)description;
+
+@property (nonatomic) CGFloat   value;
+@property (nonatomic) UIColor  *color;
+@property (nonatomic) NSString *textDescription;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.m b/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.m
new file mode 100755
index 0000000..4bda818
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNPieChartDataItem.m
@@ -0,0 +1,38 @@
+//
+//  PNPieChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Hang Zhang on 14-5-5.
+//  Copyright (c) 2014��� kevinzhow. All rights reserved.
+//
+
+#import "PNPieChartDataItem.h"
+#import <UIKit/UIKit.h>
+
+@implementation PNPieChartDataItem
+
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color{
+	PNPieChartDataItem *item = [PNPieChartDataItem new];
+	item.value = value;
+	item.color  = color;
+	return item;
+}
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                            color:(UIColor*)color
+                      description:(NSString *)description {
+	PNPieChartDataItem *item = [PNPieChartDataItem dataItemWithValue:value color:color];
+	item.textDescription = description;
+	return item;
+}
+
+- (void)setValue:(CGFloat)value{
+    NSAssert(value >= 0, @"value should >= 0");
+    if (value != _value){
+        _value = value;
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.h b/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.h
new file mode 100755
index 0000000..87871d0
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.h
@@ -0,0 +1,52 @@
+//
+//  PNRadarChart.h
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "PNGenericChart.h"
+#import "PNRadarChartDataItem.h"
+
+#define MAXCIRCLE 20
+
+typedef NS_ENUM(NSUInteger, PNRadarChartLabelStyle) {
+    PNRadarChartLabelStyleCircle = 0,
+    PNRadarChartLabelStyleHorizontal,
+    PNRadarChartLabelStyleHidden,
+};
+
+@interface PNRadarChart : PNGenericChart
+
+-(id)initWithFrame:(CGRect)frame  items:(NSArray *)items valueDivider:(CGFloat)unitValue;
+/** 
+ *Draws the chart in an animated fashion.
+ */
+-(void)strokeChart;
+
+/** Array of `RadarChartDataItem` objects, one for each corner. */
+@property (nonatomic) NSArray *chartData;
+/** The unit of this chart ,default is 1 */
+@property (nonatomic) CGFloat valueDivider;
+/** The maximum for the range of values to display on the chart */
+@property (nonatomic) CGFloat maxValue;
+/** Default is gray. */
+@property (nonatomic) UIColor *webColor;
+/** Default is green , with an alpha of 0.7 */
+@property (nonatomic) UIColor *plotColor;
+/** Default is black */
+@property (nonatomic) UIColor *fontColor;
+/** Default is orange */
+@property (nonatomic) UIColor *graduationColor;
+/** Default is 15 */
+@property (nonatomic) CGFloat fontSize;
+/** Controls the labels display style that around chart */
+@property (nonatomic, assign) PNRadarChartLabelStyle labelStyle;
+/** Tap the label will display detail value ,default is YES. */
+@property (nonatomic, assign) BOOL isLabelTouchable;
+/** is show graduation on the chart ,default is NO. */
+@property (nonatomic, assign) BOOL isShowGraduation;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.m b/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.m
new file mode 100755
index 0000000..9dace2b
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNRadarChart.m
@@ -0,0 +1,373 @@
+//
+//  PNRadarChart.m
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import "PNRadarChart.h"
+
+@interface PNRadarChart()
+
+@property (nonatomic) CGFloat centerX;
+@property (nonatomic) CGFloat centerY;
+@property (nonatomic) NSMutableArray *pointsToWebArrayArray;
+@property (nonatomic) NSMutableArray *pointsToPlotArray;
+@property (nonatomic) UILabel *detailLabel;
+@property (nonatomic) CGFloat lengthUnit;
+@property (nonatomic) CAShapeLayer *chartPlot;
+
+@end
+
+
+@implementation PNRadarChart
+
+- (id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue {
+    self=[super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = [UIColor clearColor];
+        self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+
+        //Public iVar
+        if ([items count]< 3)//At least three corners of A polygon ,If the count of items is less than 3 will add 3 default values
+        {
+            NSLog( @"At least three items!");
+            NSArray *defaultArray = @[[PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
+                                      ];
+           defaultArray = [defaultArray arrayByAddingObjectsFromArray:items];
+            _chartData = [NSArray arrayWithArray:defaultArray];
+        }else{
+            _chartData = [NSArray arrayWithArray:items];
+        }
+        _valueDivider = unitValue;
+        _maxValue = 1;
+        _webColor = [UIColor grayColor];
+        _plotColor = [UIColor colorWithRed:.4 green:.8 blue:.4 alpha:.7];
+        _fontColor = [UIColor blackColor];
+        _graduationColor = [UIColor orangeColor];
+        _fontSize = 15;
+        _labelStyle = PNRadarChartLabelStyleHorizontal;
+        _isLabelTouchable = YES;
+        _isShowGraduation = NO;
+        
+        //Private iVar
+        _centerX = frame.size.width/2;
+        _centerY = frame.size.height/2;
+        _pointsToWebArrayArray = [NSMutableArray array];
+        _pointsToPlotArray = [NSMutableArray array];
+        _lengthUnit = 0;
+        _chartPlot = [CAShapeLayer layer];
+        _chartPlot.lineCap = kCALineCapButt;
+        _chartPlot.lineWidth = 1.0;
+        [self.layer addSublayer:_chartPlot];
+        
+        [super setupDefaultValues];
+         //init detailLabel
+        _detailLabel = [[UILabel alloc] init];
+        _detailLabel.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.1 alpha:.9];
+        _detailLabel.textAlignment = NSTextAlignmentCenter;
+        _detailLabel.textColor = [UIColor colorWithWhite:1 alpha:1];
+        _detailLabel.font = [UIFont systemFontOfSize:15];
+        [_detailLabel setHidden:YES];
+        [self addSubview:_detailLabel];
+        
+        [self strokeChart];
+    }
+    return self;
+}
+
+#pragma mark - main
+- (void)calculateChartPoints {
+    [_pointsToPlotArray removeAllObjects];
+    [_pointsToWebArrayArray removeAllObjects];
+    
+    //init Descriptions , Values and Angles.
+    NSMutableArray *descriptions = [NSMutableArray array];
+    NSMutableArray *values = [NSMutableArray array];
+    NSMutableArray *angles = [NSMutableArray array];
+    for (int i=0;i<_chartData.count;i++) {
+        PNRadarChartDataItem *item = (PNRadarChartDataItem *)[_chartData objectAtIndex:i];
+        [descriptions addObject:item.textDescription];
+        [values addObject:[NSNumber numberWithFloat:item.value]];
+        CGFloat angleValue = (float)i/(float)[_chartData count]*2*M_PI;
+        [angles addObject:[NSNumber numberWithFloat:angleValue]];
+    }
+    
+    //calculate all the lengths
+    _maxValue = [self getMaxValueFromArray:values];
+    CGFloat margin = 0;
+    if (_labelStyle==PNRadarChartLabelStyleCircle) {
+        margin = MIN(_centerX , _centerY)*3/10;
+    }else if (_labelStyle==PNRadarChartLabelStyleHorizontal) {
+        margin = [self getMaxWidthLabelFromArray:descriptions withFontSize:_fontSize];
+    }
+    CGFloat maxLength = ceil(MIN(_centerX, _centerY) - margin);
+    int plotCircles = (_maxValue/_valueDivider);
+    if (plotCircles > MAXCIRCLE) {
+        NSLog(@"Circle number is higher than max");
+        plotCircles = MAXCIRCLE;
+        _valueDivider = _maxValue/plotCircles;
+    }
+    _lengthUnit = maxLength/plotCircles;
+    NSArray *lengthArray = [self getLengthArrayWithCircleNum:(int)plotCircles];
+
+    //get all the points and plot
+    for (NSNumber *lengthNumber in lengthArray) {
+        CGFloat length = [lengthNumber floatValue];
+        [_pointsToWebArrayArray addObject:[self getWebPointWithLength:length angleArray:angles]];
+    }
+    int section = 0;
+    for (id value in values) {
+        CGFloat valueFloat = [value floatValue];
+        if (valueFloat>_maxValue) {
+            NSString *reason = [NSString stringWithFormat:@"Value number is higher than max -value: %f - maxValue: %f",valueFloat,_maxValue];
+            @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
+            return;
+        }
+        
+        CGFloat length = valueFloat/_maxValue*maxLength;
+        CGFloat angle = [[angles objectAtIndex:section] floatValue];
+        CGFloat x = _centerX +length*cos(angle);
+        CGFloat y = _centerY +length*sin(angle);
+        NSValue* point = [NSValue valueWithCGPoint:CGPointMake(x, y)];
+        [_pointsToPlotArray addObject:point];
+        section++;
+    }
+    //set the labels
+    [self drawLabelWithMaxLength:maxLength labelArray:descriptions angleArray:angles];
+    
+ }
+#pragma mark - Draw
+
+- (void)drawRect:(CGRect)rect {
+    // Drawing backgound
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextClearRect(context, rect);
+    int section = 0;
+    //circles
+    for(NSArray *pointArray in _pointsToWebArrayArray){
+        //plot backgound
+        CGContextRef graphContext = UIGraphicsGetCurrentContext();
+        CGContextBeginPath(graphContext);
+        CGPoint beginPoint = [[pointArray objectAtIndex:0] CGPointValue];
+        CGContextMoveToPoint(graphContext, beginPoint.x, beginPoint.y);
+        for(NSValue* pointValue in pointArray){
+            CGPoint point = [pointValue CGPointValue];
+            CGContextAddLineToPoint(graphContext, point.x, point.y);
+        }
+        CGContextAddLineToPoint(graphContext, beginPoint.x, beginPoint.y);
+        CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
+        CGContextStrokePath(graphContext);
+        
+    }
+    //cuts
+    NSArray *largestPointArray = [_pointsToWebArrayArray lastObject];
+    for (NSValue *pointValue in largestPointArray){
+        section++;
+        if (section==1&&_isShowGraduation)continue;
+        
+        CGContextRef graphContext = UIGraphicsGetCurrentContext();
+        CGContextBeginPath(graphContext);
+        CGContextMoveToPoint(graphContext, _centerX, _centerY);
+        CGPoint point = [pointValue CGPointValue];
+        CGContextAddLineToPoint(graphContext, point.x, point.y);
+        CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
+        CGContextStrokePath(graphContext);
+    }
+    
+    
+}
+
+- (void)strokeChart {
+    
+    [self calculateChartPoints];
+    [self setNeedsDisplay];
+    [_detailLabel setHidden:YES];
+    
+    //Draw plot
+    [_chartPlot removeAllAnimations];
+    UIBezierPath *plotline = [UIBezierPath bezierPath];
+    CGPoint beginPoint = [[_pointsToPlotArray objectAtIndex:0] CGPointValue];
+    [plotline moveToPoint:CGPointMake(beginPoint.x, beginPoint.y)];
+    for(NSValue *pointValue in _pointsToPlotArray){
+        CGPoint point = [pointValue CGPointValue];
+        [plotline addLineToPoint:CGPointMake(point.x ,point.y)];
+        
+    }
+    [plotline setLineWidth:1];
+    [plotline setLineCapStyle:kCGLineCapButt];
+    
+    _chartPlot.path = plotline.CGPath;
+    
+    _chartPlot.fillColor = _plotColor.CGColor;
+
+    [self addAnimationIfNeeded];
+    [self showGraduation];
+}
+
+#pragma mark - Helper
+
+- (void)drawLabelWithMaxLength:(CGFloat)maxLength labelArray:(NSArray *)labelArray angleArray:(NSArray *)angleArray {
+    //set labels
+    int labelTag = 121;
+    while (true) {
+        UIView *label = [self viewWithTag:labelTag];
+        if(!label)break;
+        [label removeFromSuperview];
+    }
+    int section = 0;
+    CGFloat labelLength = maxLength + maxLength/10;
+    
+    for (NSString *labelString in labelArray) {
+        CGFloat angle = [[angleArray objectAtIndex:section] floatValue];
+        CGFloat x = _centerX + labelLength *cos(angle);
+        CGFloat y = _centerY + labelLength *sin(angle);
+        
+        UILabel *label = [[UILabel alloc] init] ;
+        label.backgroundColor = [UIColor clearColor];
+        label.font = [UIFont systemFontOfSize:_fontSize];
+        label.text = labelString;
+        label.tag = labelTag;
+        CGSize detailSize = [labelString sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
+        
+        switch (_labelStyle) {
+            case PNRadarChartLabelStyleCircle:
+                label.frame = CGRectMake(x-5*_fontSize/2, y-_fontSize/2, 5*_fontSize, _fontSize);
+                label.transform = CGAffineTransformMakeRotation(((float)section/[labelArray count])*(2*M_PI)+M_PI_2);
+                label.textAlignment = NSTextAlignmentCenter;
+                
+                break;
+            case PNRadarChartLabelStyleHorizontal:
+                if (x<_centerX) {
+                    label.frame = CGRectMake(x-detailSize.width, y-detailSize.height/2, detailSize.width, detailSize.height);
+                    label.textAlignment = NSTextAlignmentRight;
+                }else{
+                    label.frame = CGRectMake(x, y-detailSize.height/2, detailSize.width , detailSize.height);
+                    label.textAlignment = NSTextAlignmentLeft;
+                }
+                break;
+            case PNRadarChartLabelStyleHidden:
+                [label setHidden:YES];
+                break;
+            default:
+                break;
+        }
+        [label sizeToFit];
+        
+        label.userInteractionEnabled = YES;
+        UITapGestureRecognizer *tapLabelGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapLabel:)];
+        [label addGestureRecognizer:tapLabelGesture];
+        [self addSubview:label];
+        
+        section ++;
+    }
+    
+}
+
+- (void)tapLabel:(UITapGestureRecognizer *)recognizer {
+    UILabel *label=(UILabel*)recognizer.view;
+    _detailLabel.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y-30, 50, 25);
+    for (PNRadarChartDataItem *item in _chartData) {
+        if ([label.text isEqualToString:item.textDescription]) {
+            _detailLabel.text =  [NSString stringWithFormat:@"%.2f", item.value];
+            break;
+        }
+    }
+    [_detailLabel setHidden:NO];
+    
+}
+
+- (void)showGraduation {
+    int labelTag = 112;
+    while (true) {
+        UIView *label = [self viewWithTag:labelTag];
+        if(!label)break;
+        [label removeFromSuperview];
+    }
+    int section = 0;
+    for (NSArray *pointsArray in _pointsToWebArrayArray) {
+        section++;
+        CGPoint labelPoint = [[pointsArray objectAtIndex:0] CGPointValue];
+        UILabel *graduationLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelPoint.x-_lengthUnit, labelPoint.y-_lengthUnit*5/8, _lengthUnit*5/8, _lengthUnit)];
+        graduationLabel.adjustsFontSizeToFitWidth = YES;
+        graduationLabel.tag = labelTag;
+        graduationLabel.font = [UIFont systemFontOfSize:ceil(_lengthUnit)];
+        graduationLabel.textColor = [UIColor orangeColor];
+        graduationLabel.text = [NSString stringWithFormat:@"%.0f",_valueDivider*section];
+        [self addSubview:graduationLabel];
+        if (_isShowGraduation) {
+            [graduationLabel setHidden:NO];
+        }else{
+            [graduationLabel setHidden:YES];}
+    }
+
+}
+
+- (NSArray *)getWebPointWithLength:(CGFloat)length angleArray:(NSArray *)angleArray {
+    NSMutableArray *pointArray = [NSMutableArray array];
+    for (NSNumber *angleNumber in angleArray) {
+        CGFloat angle = [angleNumber floatValue];
+        CGFloat x = _centerX + length*cos(angle);
+        CGFloat y = _centerY + length*sin(angle);
+        [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(x,y)]];
+    }
+    return pointArray;
+    
+}
+
+- (NSArray *)getLengthArrayWithCircleNum:(int)plotCircles {
+    NSMutableArray *lengthArray = [NSMutableArray array];
+    CGFloat length = 0;
+    for (int i = 0; i < plotCircles; i++) {
+        length += _lengthUnit;
+        [lengthArray addObject:[NSNumber numberWithFloat:length]];
+    }
+    return lengthArray;
+}
+
+- (CGFloat)getMaxWidthLabelFromArray:(NSArray *)keyArray withFontSize:(CGFloat)size {
+    CGFloat maxWidth = 0;
+    for (NSString *str in keyArray) {
+        CGSize detailSize = [str sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
+        maxWidth = MAX(maxWidth, detailSize.width);
+    }
+    return maxWidth;
+}
+
+- (CGFloat)getMaxValueFromArray:(NSArray *)valueArray {
+    CGFloat max = _maxValue;
+    for (NSNumber *valueNum in valueArray) {
+        CGFloat valueFloat = [valueNum floatValue];
+        max = MAX(valueFloat, max);
+    }
+    return ceil(max);
+}
+
+- (void)addAnimationIfNeeded
+{
+    if (self.displayAnimated) {
+        CABasicAnimation *animateScale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+        animateScale.fromValue = [NSNumber numberWithFloat:0.f];
+        animateScale.toValue = [NSNumber numberWithFloat:1.0f];
+        
+        CABasicAnimation *animateMove = [CABasicAnimation animationWithKeyPath:@"position"];
+        animateMove.fromValue = [NSValue valueWithCGPoint:CGPointMake(_centerX, _centerY)];
+        animateMove.toValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
+        
+        CABasicAnimation *animateAlpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        animateAlpha.fromValue = [NSNumber numberWithFloat:0.f];
+        
+        CAAnimationGroup *aniGroup = [CAAnimationGroup animation];
+        aniGroup.duration = 1.f;
+        aniGroup.repeatCount = 1;
+        aniGroup.animations = [NSArray arrayWithObjects:animateScale,animateMove,animateAlpha, nil];
+        aniGroup.removedOnCompletion = YES;
+        
+        [_chartPlot addAnimation:aniGroup forKey:nil];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.h b/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.h
new file mode 100755
index 0000000..e67429c
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.h
@@ -0,0 +1,19 @@
+//
+//  PNRadarChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface PNRadarChartDataItem : NSObject
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                      description:(NSString *)description;
+
+@property (nonatomic) CGFloat   value;
+@property (nonatomic,copy) NSString *textDescription;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.m b/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.m
new file mode 100755
index 0000000..218ef6e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNRadarChartDataItem.m
@@ -0,0 +1,29 @@
+//
+//  PNRadarChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Lei on 15/7/1.
+//  Copyright (c) 2015��� kevinzhow. All rights reserved.
+//
+
+#import "PNRadarChartDataItem.h"
+
+@implementation PNRadarChartDataItem
+
++ (instancetype)dataItemWithValue:(CGFloat)value
+                      description:(NSString *)description {
+    PNRadarChartDataItem *item = [PNRadarChartDataItem new];
+    item.value = value;
+    item.textDescription = description;
+    return item;
+}
+
+- (void)setValue:(CGFloat)value {
+    if (value < 0) {
+        value = 0;
+        NSLog(@"Value value can not be negative");
+    }
+    _value = value;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.h b/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.h
new file mode 100755
index 0000000..aa4eab8
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.h
@@ -0,0 +1,69 @@
+//
+//  PNScatterChart.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "PNChartDelegate.h"
+#import "PNGenericChart.h"
+#import "PNScatterChartData.h"
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChart : PNGenericChart
+
+@property (nonatomic, retain) id<PNChartDelegate> delegate;
+
+/** Array of `ScatterChartData` objects, one for each line. */
+@property (nonatomic) NSArray *chartData;
+
+/** Controls whether to show the coordinate axis. Default is NO. */
+@property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis;
+@property (nonatomic) UIColor *axisColor;
+@property (nonatomic) CGFloat axisWidth;
+
+/** String formatter for float values in x-axis/y-axis labels. If not set, defaults to @"%1.f" */
+@property (nonatomic, strong) NSString *xLabelFormat;
+@property (nonatomic, strong) NSString *yLabelFormat;
+
+/** Default is true. */
+@property (nonatomic) BOOL showLabel;
+
+/** Default is 18-point Avenir Medium. */
+@property (nonatomic) UIFont  *descriptionTextFont;
+
+/** Default is white. */
+@property (nonatomic) UIColor *descriptionTextColor;
+
+/** Default is black, with an alpha of 0.4. */
+@property (nonatomic) UIColor *descriptionTextShadowColor;
+
+/** Default is CGSizeMake(0, 1). */
+@property (nonatomic) CGSize   descriptionTextShadowOffset;
+
+/** Default is 1.0. */
+@property (nonatomic) NSTimeInterval duration;
+
+@property (nonatomic) CGFloat AxisX_minValue;
+@property (nonatomic) CGFloat AxisX_maxValue;
+
+@property (nonatomic) CGFloat AxisY_minValue;
+@property (nonatomic) CGFloat AxisY_maxValue;
+
+- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
+- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
+- (void) setAxisXLabel:(NSArray *)array;
+- (void) setAxisYLabel:(NSArray *)array;
+- (void) setup;
+- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color;
+
+/**
+ * Update Chart Value
+ */
+
+- (void)updateChartData:(NSArray *)data;
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.m b/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.m
new file mode 100755
index 0000000..a16cf85
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChart.m
@@ -0,0 +1,445 @@
+//
+//  PNScatterChart.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChart.h"
+#import "PNColor.h"
+#import "PNChartLabel.h"
+#import "PNScatterChartData.h"
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChart ()
+
+@property (nonatomic, weak) CAShapeLayer *pathLayer;
+@property (nonatomic, weak) NSMutableArray *verticalLineLayer;
+@property (nonatomic, weak) NSMutableArray *horizentalLinepathLayer;
+
+@property (nonatomic) CGPoint startPoint;
+
+@property (nonatomic) CGPoint startPointVectorX;
+@property (nonatomic) CGPoint endPointVecotrX;
+
+@property (nonatomic) CGPoint startPointVectorY;
+@property (nonatomic) CGPoint endPointVecotrY;
+
+@property (nonatomic) CGFloat vectorX_Steps;
+@property (nonatomic) CGFloat vectorY_Steps;
+
+@property (nonatomic) CGFloat vectorX_Size;
+@property (nonatomic) CGFloat vectorY_Size;
+
+@property (nonatomic) NSMutableArray *axisX_labels;
+@property (nonatomic) NSMutableArray *axisY_labels;
+
+@property (nonatomic) int AxisX_partNumber ;
+@property (nonatomic) int AxisY_partNumber ;
+
+@property (nonatomic) CGFloat AxisX_step ;
+@property (nonatomic) CGFloat AxisY_step ;
+
+@property (nonatomic) CGFloat AxisX_Margin;
+@property (nonatomic) CGFloat AxisY_Margin;
+
+@property (nonatomic) BOOL isForUpdate;
+
+@end
+
+
+@implementation PNScatterChart
+
+#pragma mark initialization
+
+- (id)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    
+    if (self) {
+        [self setupDefaultValues];
+    }
+    return self;
+}
+
+- (void) setup
+{
+    [self vectorXSetup];
+    [self vectorYSetup];
+}
+
+- (void)setupDefaultValues
+{
+    [super setupDefaultValues];
+    
+    // Initialization code
+    self.backgroundColor = [UIColor whiteColor];
+    self.clipsToBounds   = YES;
+    _showLabel           = YES;
+    _isForUpdate         = NO;
+    self.userInteractionEnabled = YES;
+    
+    // Coordinate Axis Default Values
+    _showCoordinateAxis = YES;
+    _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f];
+    _axisWidth = 1.f;
+    
+    // Initialization code
+    _AxisX_Margin = 30 ;
+    _AxisY_Margin = 30 ;
+    
+//    self.frame = CGRectMake((SCREEN_WIDTH - self.frame.size.width) / 2, 200, self.frame.size.width, self.frame.size.height) ;
+    self.backgroundColor = [UIColor clearColor];
+    
+    _startPoint.y = self.frame.size.height - self.AxisY_Margin ;
+    _startPoint.x = self.AxisX_Margin ;
+    
+    _axisX_labels = [NSMutableArray array];
+    _axisY_labels = [NSMutableArray array];
+    
+    _descriptionTextColor = [UIColor blackColor];
+    _descriptionTextFont  = [UIFont fontWithName:@"Avenir-Medium" size:9.0];
+    _descriptionTextShadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
+    _descriptionTextShadowOffset =  CGSizeMake(0, 1);
+    _duration = 1.0;
+    
+}
+
+#pragma mark calculating axis
+
+- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
+{
+    _AxisX_minValue = minVal ;
+    _AxisX_maxValue = maxVal ;
+    _AxisX_partNumber = numberOfTicks - 1;
+    _AxisX_step = (float)((maxVal - minVal)/_AxisX_partNumber);
+    
+    NSString *LabelFormat = self.xLabelFormat ? : @"%1.f";
+    CGFloat tempValue = minVal ;
+    UILabel *label = [[UILabel alloc] init];
+    label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
+    [_axisX_labels addObject:label];
+    for (int i = 0 ; i < _AxisX_partNumber; i++) {
+        tempValue = tempValue + _AxisX_step;
+        UILabel *tempLabel = [[UILabel alloc] init];
+        tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
+        [_axisX_labels addObject:tempLabel];
+    }
+}
+
+- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
+{
+    _AxisY_minValue = minVal ;
+    _AxisY_maxValue = maxVal ;
+    _AxisY_partNumber = numberOfTicks - 1;
+    _AxisY_step = (float)((maxVal - minVal)/_AxisY_partNumber);
+    
+    NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
+    CGFloat tempValue = minVal ;
+    UILabel *label = [[UILabel alloc] init];
+    label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
+    [_axisY_labels addObject:label];
+    for (int i = 0 ; i < _AxisY_partNumber; i++) {
+        tempValue = tempValue + _AxisY_step;
+        UILabel *tempLabel = [[UILabel alloc] init];
+        tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
+        [_axisY_labels addObject:tempLabel];
+    }
+}
+
+- (NSArray*) getAxisMinMax:(NSArray*)xValues
+{
+    float min = [xValues[0] floatValue];
+    float max = [xValues[0] floatValue];
+    for (NSNumber *number in xValues)
+    {
+        if ([number floatValue] > max)
+            max = [number floatValue];
+        
+        if ([number floatValue] < min)
+            min = [number floatValue];
+    }
+    NSArray *result = @[[NSNumber numberWithFloat:min], [NSNumber numberWithFloat:max]];
+   
+    
+    return result;
+}
+
+- (void)setAxisXLabel:(NSArray *)array {
+    if(array.count == ++_AxisX_partNumber){
+        [_axisX_labels removeAllObjects];
+        for(int i=0;i<array.count;i++){
+            UILabel *label = [[UILabel alloc] init];
+            label.text = [array objectAtIndex:i];
+            [_axisX_labels addObject:label];
+        }
+    }
+}
+
+- (void)setAxisYLabel:(NSArray *)array {
+    if(array.count == ++_AxisY_partNumber){
+        [_axisY_labels removeAllObjects];
+        for(int i=0;i<array.count;i++){
+            UILabel *label = [[UILabel alloc] init];
+            label.text = [array objectAtIndex:i];
+            [_axisY_labels addObject:label];
+        }
+    }
+}
+
+- (void) vectorXSetup
+{
+    _AxisX_partNumber += 1;
+    _vectorX_Size = self.frame.size.width - (_AxisX_Margin) - 15 ;
+    _vectorX_Steps = (_vectorX_Size) / (_AxisX_partNumber) ;
+    _endPointVecotrX = CGPointMake(_startPoint.x + _vectorX_Size, _startPoint.y) ;
+    _startPointVectorX = _startPoint ;
+}
+
+- (void) vectorYSetup
+{
+    _AxisY_partNumber += 1;
+    _vectorY_Size = self.frame.size.height - (_AxisY_Margin) - 15;
+    _vectorY_Steps = (_vectorY_Size) / (_AxisY_partNumber);
+    _endPointVecotrY = CGPointMake(_startPoint.x, _startPoint.y - _vectorY_Size) ;
+    _startPointVectorY = _startPoint ;
+}
+
+- (void) showXLabel : (UILabel *) descriptionLabel InPosition : (CGPoint) point
+{
+    CGRect frame = CGRectMake(point.x, point.y, 30, 10);
+    descriptionLabel.frame = frame;
+    descriptionLabel.font = _descriptionTextFont;
+    descriptionLabel.textColor = _descriptionTextColor;
+    descriptionLabel.shadowColor = _descriptionTextShadowColor;
+    descriptionLabel.shadowOffset = _descriptionTextShadowOffset;
+    descriptionLabel.textAlignment = NSTextAlignmentCenter;
+    descriptionLabel.backgroundColor = [UIColor clearColor];
+    [self addSubview:descriptionLabel];
+}
+
+- (void)setChartData:(NSArray *)data
+{
+    __block CGFloat yFinilizeValue , xFinilizeValue;
+    __block CGFloat yValue , xValue;
+
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        if (self.displayAnimated) {
+            [NSThread sleepForTimeInterval:1];
+        }
+        // update UI on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            for (PNScatterChartData *chartData in data) {
+                for (NSUInteger i = 0; i < chartData.itemCount; i++) {
+                    yValue = chartData.getData(i).y;
+                    xValue = chartData.getData(i).x;
+                    if (!(xValue >= _AxisX_minValue && xValue <= _AxisX_maxValue) || !(yValue >= _AxisY_minValue && yValue <= _AxisY_maxValue)) {
+                        NSLog(@"input is not in correct range.");
+                        exit(0);
+                    }
+                    xFinilizeValue = [self mappingIsForAxisX:true WithValue:xValue];
+                    yFinilizeValue = [self mappingIsForAxisX:false WithValue:yValue];
+                    CAShapeLayer *shape = [self drawingPointsForChartData:chartData AndWithX:xFinilizeValue AndWithY:yFinilizeValue];
+                    self.pathLayer = shape ;
+                    [self.layer addSublayer:self.pathLayer];
+                    
+                    [self addAnimationIfNeeded];
+                }
+            }
+        });
+    });
+}
+
+- (void)addAnimationIfNeeded{
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        pathAnimation.duration = _duration;
+        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        pathAnimation.fromValue = @(0.0f);
+        pathAnimation.toValue = @(1.0f);
+        pathAnimation.fillMode = kCAFillModeForwards;
+        self.layer.opacity = 1;
+        [self.pathLayer addAnimation:pathAnimation forKey:@"fade"];
+    }
+}
+
+- (CGFloat) mappingIsForAxisX : (BOOL) isForAxisX WithValue : (CGFloat) value{
+    
+    if (isForAxisX) {
+        float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
+        CGFloat xPos = temp + (((value - _AxisX_minValue)/_AxisX_step) * _vectorX_Steps) ;
+        return xPos;
+    }
+    else {
+        float temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
+        CGFloat yPos = temp - (((value - _AxisY_minValue) /_AxisY_step) * _vectorY_Steps);
+        return yPos;
+    }
+    return 0;
+}
+
+#pragma mark - Update Chart Data
+
+- (void)updateChartData:(NSArray *)data
+{
+    _chartData = data;
+
+    // will be work in future.
+}
+
+#pragma drawing methods
+
+- (void)drawRect:(CGRect)rect
+{
+    [super drawRect:rect];
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+        if (_showCoordinateAxis) {
+            CGContextSetStrokeColorWithColor(context, [_axisColor CGColor]);
+            CGContextSetLineWidth(context, _axisWidth);
+            //drawing x vector
+            CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            //drawing y vector
+            CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            //drawing x arrow vector
+            CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y + 3);
+            CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
+            CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y - 3);
+            //drawing y arrow vector
+            CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x - 3, _endPointVecotrY.y + 5);
+            CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
+            CGContextAddLineToPoint(context, _endPointVecotrY.x + 3, _endPointVecotrY.y + 5);
+        }
+    
+    if (_showLabel) {
+        //drawing x steps vector and putting axis x labels
+        float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
+        for (int i = 0; i < _axisX_labels.count; i++) {
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(temp, _startPointVectorX.y - 2)];
+            [path addLineToPoint:CGPointMake(temp, _startPointVectorX.y + 3)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [_axisColor CGColor];
+            shapeLayer.lineWidth = _axisWidth;
+            shapeLayer.fillColor = [_axisColor CGColor];
+            [self.horizentalLinepathLayer addObject:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+            UILabel *lb = [_axisX_labels objectAtIndex:i] ;
+            [self showXLabel:lb InPosition:CGPointMake(temp - 15, _startPointVectorX.y + 10 )];
+            temp = temp + _vectorX_Steps ;
+        }
+        //drawing y steps vector and putting axis x labels
+        temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
+        for (int i = 0; i < _axisY_labels.count; i++) {
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(_startPointVectorY.x - 3, temp)];
+            [path addLineToPoint:CGPointMake( _startPointVectorY.x + 2, temp)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [_axisColor CGColor];
+            shapeLayer.lineWidth = _axisWidth;
+            shapeLayer.fillColor = [_axisColor CGColor];
+            [self.verticalLineLayer addObject:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+            UILabel *lb = [_axisY_labels objectAtIndex:i];
+            [self showXLabel:lb InPosition:CGPointMake(_startPointVectorY.x - 30, temp - 5)];
+            temp = temp - _vectorY_Steps ;
+        }
+    }
+    CGContextDrawPath(context, kCGPathStroke);
+}
+
+- (CAShapeLayer*) drawingPointsForChartData : (PNScatterChartData *) chartData AndWithX : (CGFloat) X AndWithY : (CGFloat) Y
+{
+    if (chartData.inflexionPointStyle == PNScatterChartPointStyleCircle) {
+        float radius = chartData.size;
+        CAShapeLayer *circle = [CAShapeLayer layer];
+        // Make a circular shape
+        circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(X - radius, Y - radius, 2.0*radius, 2.0*radius)
+                                                 cornerRadius:radius].CGPath;
+        // Configure the appearence of the circle
+        circle.fillColor = [chartData.fillColor CGColor];
+        circle.strokeColor = [chartData.strokeColor CGColor];
+        circle.lineWidth = 1;
+        
+        // Add to parent layer
+        return circle;
+    }
+    else if (chartData.inflexionPointStyle == PNScatterChartPointStyleSquare) {
+        float side = chartData.size;
+        CAShapeLayer *square = [CAShapeLayer layer];
+        // Make a circular shape
+        square.path = [UIBezierPath bezierPathWithRect:CGRectMake(X - (side/2) , Y - (side/2), side, side)].CGPath ;
+        // Configure the apperence of the circle
+        square.fillColor = [chartData.fillColor CGColor];
+        square.strokeColor = [chartData.strokeColor CGColor];
+        square.lineWidth = 1;
+        
+        // Add to parent layer
+        return square;
+    }
+    else {
+        // you cann add your own scatter chart point here
+    }
+    return nil ;
+}
+
+- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color{
+    
+    // call the same method on a background thread
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        if (self.displayAnimated) {
+            [NSThread sleepForTimeInterval:2];
+        }
+        // calculating start and end point
+        __block CGFloat startX = [self mappingIsForAxisX:true WithValue:startPoint.x];
+        __block CGFloat startY = [self mappingIsForAxisX:false WithValue:startPoint.y];
+        __block CGFloat endX = [self mappingIsForAxisX:true WithValue:endPoint.x];
+        __block CGFloat endY = [self mappingIsForAxisX:false WithValue:endPoint.y];
+        // update UI on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            // drawing path between two points
+            UIBezierPath *path = [UIBezierPath bezierPath];
+            [path moveToPoint:CGPointMake(startX, startY)];
+            [path addLineToPoint:CGPointMake(endX, endY)];
+            CAShapeLayer *shapeLayer = [CAShapeLayer layer];
+            shapeLayer.path = [path CGPath];
+            shapeLayer.strokeColor = [color CGColor];
+            shapeLayer.lineWidth = lineWidth;
+            shapeLayer.fillColor = [color CGColor];
+            // adding animation to path
+            [self addStrokeEndAnimationIfNeededToLayer:shapeLayer];
+            [self.layer addSublayer:shapeLayer];
+        });
+    });
+}
+
+- (void)addStrokeEndAnimationIfNeededToLayer:(CAShapeLayer *)shapeLayer{
+    
+    if (self.displayAnimated) {
+        CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        animateStrokeEnd.duration  = _duration;
+        animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f];
+        animateStrokeEnd.toValue   = [NSNumber numberWithFloat:1.0f];
+        [shapeLayer addAnimation:animateStrokeEnd forKey:nil];
+    }
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.h b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.h
new file mode 100755
index 0000000..40b7b0e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.h
@@ -0,0 +1,38 @@
+//
+//  PNScatterChartData.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSUInteger, PNScatterChartPointStyle) {
+    PNScatterChartPointStyleCircle = 0,
+    PNScatterChartPointStyleSquare = 1,
+};
+
+@class PNScatterChartDataItem;
+
+typedef PNScatterChartDataItem *(^LCScatterChartDataGetter)(NSUInteger item);
+
+@interface PNScatterChartData : NSObject
+
+@property (strong) UIColor *fillColor;
+@property (strong) UIColor *strokeColor;
+
+@property NSUInteger itemCount;
+@property (copy) LCScatterChartDataGetter getData;
+
+@property (nonatomic, assign) PNScatterChartPointStyle inflexionPointStyle;
+
+/**
+ * If PNLineChartPointStyle is circle, this returns the circle's diameter.
+ * If PNLineChartPointStyle is square, each point is a square with each side equal in length to this value.
+ */
+@property (nonatomic, assign) CGFloat size;
+
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.m b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.m
new file mode 100755
index 0000000..a53a5c2
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartData.m
@@ -0,0 +1,31 @@
+//
+//  PNScatterChartData.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChartData.h"
+
+@implementation PNScatterChartData
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        [self setupDefaultValues];
+    }
+    
+    return self;
+}
+
+- (void)setupDefaultValues
+{
+    _inflexionPointStyle = PNScatterChartPointStyleCircle;
+    _fillColor = [UIColor grayColor];
+    _strokeColor = [UIColor clearColor];
+    _size = 3 ;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.h b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.h
new file mode 100755
index 0000000..f38ee4e
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.h
@@ -0,0 +1,19 @@
+//
+//  PNScatterChartDataItem.h
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface PNScatterChartDataItem : NSObject
+
++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y;
+
+@property (readonly) CGFloat x; // should be within the x range
+@property (readonly) CGFloat y; // should be within the y range
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.m b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.m
new file mode 100755
index 0000000..a454459
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChart/PNScatterChartDataItem.m
@@ -0,0 +1,37 @@
+//
+//  PNScatterChartDataItem.m
+//  PNChartDemo
+//
+//  Created by Alireza Arabi on 12/4/14.
+//  Copyright (c) 2014 kevinzhow. All rights reserved.
+//
+
+#import "PNScatterChartDataItem.h"
+
+@interface PNScatterChartDataItem ()
+
+- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y;
+
+@property (readwrite) CGFloat x; // should be within the x range
+@property (readwrite) CGFloat y; // should be within the y range
+
+@end
+
+@implementation PNScatterChartDataItem
+
++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y
+{
+    return [[PNScatterChartDataItem alloc] initWithX:x AndWithY:y];
+}
+
+- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y
+{
+    if ((self = [super init])) {
+        self.x = x;
+        self.y = y;
+    }
+    
+    return self;
+}
+
+@end
diff --git a/PNChartdemo/PNChartdemo/PNChartDemo-Prefix.pch b/PNChartdemo/PNChartdemo/PNChartDemo-Prefix.pch
new file mode 100755
index 0000000..a0c6545
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/PNChartDemo-Prefix.pch
@@ -0,0 +1,16 @@
+//
+//  Prefix header
+//
+//  The contents of this file are implicitly included at the beginning of every source file.
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_5_0
+#warning "This project uses features only available in iOS SDK 5.0 and later."
+#endif
+
+#ifdef __OBJC__
+	#import <UIKit/UIKit.h>
+	#import <Foundation/Foundation.h>
+#endif
diff --git a/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.h b/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.h
new file mode 100755
index 0000000..3c59ee3
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.h
@@ -0,0 +1,36 @@
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, UILabelCountingMethod) {
+    UILabelCountingMethodEaseInOut,
+    UILabelCountingMethodEaseIn,
+    UILabelCountingMethodEaseOut,
+    UILabelCountingMethodLinear
+};
+
+typedef NSString* (^UICountingLabelFormatBlock)(CGFloat value);
+typedef NSAttributedString* (^UICountingLabelAttributedFormatBlock)(CGFloat value);
+
+@interface UICountingLabel : UILabel
+
+@property (nonatomic, strong) NSString *format;
+@property (nonatomic, assign) UILabelCountingMethod method;
+@property (nonatomic, assign) NSTimeInterval animationDuration;
+
+@property (nonatomic, copy) UICountingLabelFormatBlock formatBlock;
+@property (nonatomic, copy) UICountingLabelAttributedFormatBlock attributedFormatBlock;
+@property (nonatomic, copy) void (^completionBlock)();
+
+-(void)countFrom:(CGFloat)startValue to:(CGFloat)endValue;
+-(void)countFrom:(CGFloat)startValue to:(CGFloat)endValue withDuration:(NSTimeInterval)duration;
+
+-(void)countFromCurrentValueTo:(CGFloat)endValue;
+-(void)countFromCurrentValueTo:(CGFloat)endValue withDuration:(NSTimeInterval)duration;
+
+-(void)countFromZeroTo:(CGFloat)endValue;
+-(void)countFromZeroTo:(CGFloat)endValue withDuration:(NSTimeInterval)duration;
+
+- (CGFloat)currentValue;
+
+@end
+
diff --git a/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.m b/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.m
new file mode 100755
index 0000000..3a75a50
--- /dev/null
+++ b/PNChartdemo/PNChartdemo/UICountingLabel/UICountingLabel.m
@@ -0,0 +1,234 @@
+#import <QuartzCore/QuartzCore.h>
+
+#import "UICountingLabel.h"
+
+#if !__has_feature(objc_arc)
+#error UICountingLabel is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
+#endif
+
+#pragma mark - UILabelCounter
+
+#ifndef kUILabelCounterRate
+#define kUILabelCounterRate 3.0
+#endif
+
+@protocol UILabelCounter<NSObject>
+
+-(CGFloat)update:(CGFloat)t;
+
+@end
+
+@interface UILabelCounterLinear : NSObject<UILabelCounter>
+
+@end
+
+@interface UILabelCounterEaseIn : NSObject<UILabelCounter>
+
+@end
+
+@interface UILabelCounterEaseOut : NSObject<UILabelCounter>
+
+@end
+
+@interface UILabelCounterEaseInOut : NSObject<UILabelCounter>
+
+@end
+
+@implementation UILabelCounterLinear
+
+-(CGFloat)update:(CGFloat)t
+{
+    return t;
+}
+
+@end
+
+@implementation UILabelCounterEaseIn
+
+-(CGFloat)update:(CGFloat)t
+{
+    return powf(t, kUILabelCounterRate);
+}
+
+@end
+
+@implementation UILabelCounterEaseOut
+
+-(CGFloat)update:(CGFloat)t{
+    return 1.0-powf((1.0-t), kUILabelCounterRate);
+}
+
+@end
+
+@implementation UILabelCounterEaseInOut
+
+-(CGFloat) update: (CGFloat) t
+{
+    t *= 2;
+    if (t < 1)
+        return 0.5f * powf (t, kUILabelCounterRate);
+    else
+        return 0.5f * (2.0f - powf(2.0 - t, kUILabelCounterRate));
+}
+
+@end
+
+#pragma mark - UICountingLabel
+
+@interface UICountingLabel ()
+
+@property CGFloat startingValue;
+@property CGFloat destinationValue;
+@property NSTimeInterval progress;
+@property NSTimeInterval lastUpdate;
+@property NSTimeInterval totalTime;
+@property CGFloat easingRate;
+
+@property (nonatomic, strong) CADisplayLink *timer;
+@property (nonatomic, strong) id<UILabelCounter> counter;
+
+@end
+
+@implementation UICountingLabel
+
+-(void)countFrom:(CGFloat)value to:(CGFloat)endValue {
+    
+    if (self.animationDuration == 0.0f) {
+        self.animationDuration = 2.0f;
+    }
+    
+    [self countFrom:value to:endValue withDuration:self.animationDuration];
+}
+
+-(void)countFrom:(CGFloat)startValue to:(CGFloat)endValue withDuration:(NSTimeInterval)duration {
+    
+    self.startingValue = startValue;
+    self.destinationValue = endValue;
+    
+    // remove any (possible) old timers
+    [self.timer invalidate];
+    self.timer = nil;
+    
+    if (duration == 0.0) {
+        // No animation
+        [self setTextValue:endValue];
+        [self runCompletionBlock];
+        return;
+    }
+
+    self.easingRate = 3.0f;
+    self.progress = 0;
+    self.totalTime = duration;
+    self.lastUpdate = [NSDate timeIntervalSinceReferenceDate];
+
+    if(self.format == nil)
+        self.format = @"%f";
+
+    switch(self.method)
+    {
+        case UILabelCountingMethodLinear:
+            self.counter = [[UILabelCounterLinear alloc] init];
+            break;
+        case UILabelCountingMethodEaseIn:
+            self.counter = [[UILabelCounterEaseIn alloc] init];
+            break;
+        case UILabelCountingMethodEaseOut:
+            self.counter = [[UILabelCounterEaseOut alloc] init];
+            break;
+        case UILabelCountingMethodEaseInOut:
+            self.counter = [[UILabelCounterEaseInOut alloc] init];
+            break;
+    }
+
+    CADisplayLink *timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateValue:)];
+    timer.frameInterval = 2;
+    [timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+    [timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];
+    self.timer = timer;
+}
+
+- (void)countFromCurrentValueTo:(CGFloat)endValue {
+    [self countFrom:[self currentValue] to:endValue];
+}
+
+- (void)countFromCurrentValueTo:(CGFloat)endValue withDuration:(NSTimeInterval)duration {
+    [self countFrom:[self currentValue] to:endValue withDuration:duration];
+}
+
+- (void)countFromZeroTo:(CGFloat)endValue {
+    [self countFrom:0.0f to:endValue];
+}
+
+- (void)countFromZeroTo:(CGFloat)endValue withDuration:(NSTimeInterval)duration {
+    [self countFrom:0.0f to:endValue withDuration:duration];
+}
+
+- (void)updateValue:(NSTimer *)timer {
+    
+    // update progress
+    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
+    self.progress += now - self.lastUpdate;
+    self.lastUpdate = now;
+    
+    if (self.progress >= self.totalTime) {
+        [self.timer invalidate];
+        self.timer = nil;
+        self.progress = self.totalTime;
+    }
+    
+    [self setTextValue:[self currentValue]];
+    
+    if (self.progress == self.totalTime) {
+        [self runCompletionBlock];
+    }
+}
+
+- (void)setTextValue:(CGFloat)value
+{
+    if (self.attributedFormatBlock != nil) {
+        self.attributedText = self.attributedFormatBlock(value);
+    }
+    else if(self.formatBlock != nil)
+    {
+        self.text = self.formatBlock(value);
+    }
+    else
+    {
+        // check if counting with ints - cast to int
+        if([self.format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound || [self.format rangeOfString:@"%(.*)i"].location != NSNotFound )
+        {
+            self.text = [NSString stringWithFormat:self.format,(int)value];
+        }
+        else
+        {
+            self.text = [NSString stringWithFormat:self.format,value];
+        }
+    }
+}
+
+- (void)setFormat:(NSString *)format {
+    _format = format;
+    // update label with new format
+    [self setTextValue:self.currentValue];
+}
+
+- (void)runCompletionBlock {
+    
+    if (self.completionBlock) {
+        self.completionBlock();
+        self.completionBlock = nil;
+    }
+}
+
+- (CGFloat)currentValue {
+    
+    if (self.progress >= self.totalTime) {
+        return self.destinationValue;
+    }
+    
+    CGFloat percent = self.progress / self.totalTime;
+    CGFloat updateVal = [self.counter update:percent];
+    return self.startingValue + (updateVal * (self.destinationValue - self.startingValue));
+}
+
+@end
diff --git a/camerademo/camerademo/ViewController.h b/PNChartdemo/PNChartdemo/ViewController.h
similarity index 75%
rename from camerademo/camerademo/ViewController.h
rename to PNChartdemo/PNChartdemo/ViewController.h
index ca96e2d..fbaa548 100644
--- a/camerademo/camerademo/ViewController.h
+++ b/PNChartdemo/PNChartdemo/ViewController.h
@@ -1,8 +1,8 @@
 //
 //  ViewController.h
-//  camerademo
+//  PNChartdemo
 //
-//  Created by WindShan on 2017/2/21.
+//  Created by WindShan on 2017/3/3.
 //  Copyright �� 2017��� WindShan. All rights reserved.
 //
 
diff --git a/camerademo/camerademo/ViewController.m b/PNChartdemo/PNChartdemo/ViewController.m
similarity index 89%
rename from camerademo/camerademo/ViewController.m
rename to PNChartdemo/PNChartdemo/ViewController.m
index d49c4e7..93fbcb3 100644
--- a/camerademo/camerademo/ViewController.m
+++ b/PNChartdemo/PNChartdemo/ViewController.m
@@ -1,8 +1,8 @@
 //
 //  ViewController.m
-//  camerademo
+//  PNChartdemo
 //
-//  Created by WindShan on 2017/2/21.
+//  Created by WindShan on 2017/3/3.
 //  Copyright �� 2017��� WindShan. All rights reserved.
 //
 
diff --git a/camerademo/camerademo/main.m b/PNChartdemo/PNChartdemo/main.m
similarity index 83%
rename from camerademo/camerademo/main.m
rename to PNChartdemo/PNChartdemo/main.m
index 27a8a02..c92139f 100644
--- a/camerademo/camerademo/main.m
+++ b/PNChartdemo/PNChartdemo/main.m
@@ -1,8 +1,8 @@
 //
 //  main.m
-//  camerademo
+//  PNChartdemo
 //
-//  Created by WindShan on 2017/2/21.
+//  Created by WindShan on 2017/3/3.
 //  Copyright �� 2017��� WindShan. All rights reserved.
 //
 
diff --git a/camerademo/camerademo.xcodeproj/project.pbxproj b/camerademo/camerademo.xcodeproj/project.pbxproj
deleted file mode 100644
index a75fd57..0000000
--- a/camerademo/camerademo.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,317 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 46;
-	objects = {
-
-/* Begin PBXBuildFile section */
-		E52F59F01E5C21890084B3E2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E52F59EF1E5C21890084B3E2 /* main.m */; };
-		E52F59F31E5C21890084B3E2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E52F59F21E5C21890084B3E2 /* AppDelegate.m */; };
-		E52F59F61E5C21890084B3E2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E52F59F51E5C21890084B3E2 /* ViewController.m */; };
-		E52F59F91E5C21890084B3E2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E52F59F71E5C21890084B3E2 /* Main.storyboard */; };
-		E52F59FB1E5C21890084B3E2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E52F59FA1E5C21890084B3E2 /* Assets.xcassets */; };
-		E52F59FE1E5C21890084B3E2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E52F59FC1E5C21890084B3E2 /* LaunchScreen.storyboard */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
-		E52F59EB1E5C21890084B3E2 /* camerademo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = camerademo.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		E52F59EF1E5C21890084B3E2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
-		E52F59F11E5C21890084B3E2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
-		E52F59F21E5C21890084B3E2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
-		E52F59F41E5C21890084B3E2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
-		E52F59F51E5C21890084B3E2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
-		E52F59F81E5C21890084B3E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
-		E52F59FA1E5C21890084B3E2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		E52F59FD1E5C21890084B3E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
-		E52F59FF1E5C21890084B3E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
-		E52F59E81E5C21890084B3E2 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
-		E52F59E21E5C21890084B3E2 = {
-			isa = PBXGroup;
-			children = (
-				E52F59ED1E5C21890084B3E2 /* camerademo */,
-				E52F59EC1E5C21890084B3E2 /* Products */,
-			);
-			sourceTree = "<group>";
-		};
-		E52F59EC1E5C21890084B3E2 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				E52F59EB1E5C21890084B3E2 /* camerademo.app */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		E52F59ED1E5C21890084B3E2 /* camerademo */ = {
-			isa = PBXGroup;
-			children = (
-				E52F59F11E5C21890084B3E2 /* AppDelegate.h */,
-				E52F59F21E5C21890084B3E2 /* AppDelegate.m */,
-				E52F59F41E5C21890084B3E2 /* ViewController.h */,
-				E52F59F51E5C21890084B3E2 /* ViewController.m */,
-				E52F59F71E5C21890084B3E2 /* Main.storyboard */,
-				E52F59FA1E5C21890084B3E2 /* Assets.xcassets */,
-				E52F59FC1E5C21890084B3E2 /* LaunchScreen.storyboard */,
-				E52F59FF1E5C21890084B3E2 /* Info.plist */,
-				E52F59EE1E5C21890084B3E2 /* Supporting Files */,
-			);
-			path = camerademo;
-			sourceTree = "<group>";
-		};
-		E52F59EE1E5C21890084B3E2 /* Supporting Files */ = {
-			isa = PBXGroup;
-			children = (
-				E52F59EF1E5C21890084B3E2 /* main.m */,
-			);
-			name = "Supporting Files";
-			sourceTree = "<group>";
-		};
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
-		E52F59EA1E5C21890084B3E2 /* camerademo */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = E52F5A021E5C21890084B3E2 /* Build configuration list for PBXNativeTarget "camerademo" */;
-			buildPhases = (
-				E52F59E71E5C21890084B3E2 /* Sources */,
-				E52F59E81E5C21890084B3E2 /* Frameworks */,
-				E52F59E91E5C21890084B3E2 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = camerademo;
-			productName = camerademo;
-			productReference = E52F59EB1E5C21890084B3E2 /* camerademo.app */;
-			productType = "com.apple.product-type.application";
-		};
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
-		E52F59E31E5C21890084B3E2 /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-				LastUpgradeCheck = 0820;
-				ORGANIZATIONNAME = WindShan;
-				TargetAttributes = {
-					E52F59EA1E5C21890084B3E2 = {
-						CreatedOnToolsVersion = 8.2.1;
-						DevelopmentTeam = VGXA77XL6T;
-						ProvisioningStyle = Automatic;
-					};
-				};
-			};
-			buildConfigurationList = E52F59E61E5C21890084B3E2 /* Build configuration list for PBXProject "camerademo" */;
-			compatibilityVersion = "Xcode 3.2";
-			developmentRegion = English;
-			hasScannedForEncodings = 0;
-			knownRegions = (
-				en,
-				Base,
-			);
-			mainGroup = E52F59E21E5C21890084B3E2;
-			productRefGroup = E52F59EC1E5C21890084B3E2 /* Products */;
-			projectDirPath = "";
-			projectRoot = "";
-			targets = (
-				E52F59EA1E5C21890084B3E2 /* camerademo */,
-			);
-		};
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
-		E52F59E91E5C21890084B3E2 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				E52F59FE1E5C21890084B3E2 /* LaunchScreen.storyboard in Resources */,
-				E52F59FB1E5C21890084B3E2 /* Assets.xcassets in Resources */,
-				E52F59F91E5C21890084B3E2 /* Main.storyboard in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
-		E52F59E71E5C21890084B3E2 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				E52F59F61E5C21890084B3E2 /* ViewController.m in Sources */,
-				E52F59F31E5C21890084B3E2 /* AppDelegate.m in Sources */,
-				E52F59F01E5C21890084B3E2 /* main.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
-		E52F59F71E5C21890084B3E2 /* Main.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				E52F59F81E5C21890084B3E2 /* Base */,
-			);
-			name = Main.storyboard;
-			sourceTree = "<group>";
-		};
-		E52F59FC1E5C21890084B3E2 /* LaunchScreen.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				E52F59FD1E5C21890084B3E2 /* Base */,
-			);
-			name = LaunchScreen.storyboard;
-			sourceTree = "<group>";
-		};
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
-		E52F5A001E5C21890084B3E2 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = dwarf;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				ENABLE_TESTABILITY = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-				);
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
-				MTL_ENABLE_DEBUG_INFO = YES;
-				ONLY_ACTIVE_ARCH = YES;
-				SDKROOT = iphoneos;
-			};
-			name = Debug;
-		};
-		E52F5A011E5C21890084B3E2 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				ENABLE_NS_ASSERTIONS = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
-				MTL_ENABLE_DEBUG_INFO = NO;
-				SDKROOT = iphoneos;
-				VALIDATE_PRODUCT = YES;
-			};
-			name = Release;
-		};
-		E52F5A031E5C21890084B3E2 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				DEVELOPMENT_TEAM = VGXA77XL6T;
-				INFOPLIST_FILE = camerademo/Info.plist;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				PRODUCT_BUNDLE_IDENTIFIER = com.moral.camerademo.camerademo;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Debug;
-		};
-		E52F5A041E5C21890084B3E2 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				DEVELOPMENT_TEAM = VGXA77XL6T;
-				INFOPLIST_FILE = camerademo/Info.plist;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				PRODUCT_BUNDLE_IDENTIFIER = com.moral.camerademo.camerademo;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-			};
-			name = Release;
-		};
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-		E52F59E61E5C21890084B3E2 /* Build configuration list for PBXProject "camerademo" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				E52F5A001E5C21890084B3E2 /* Debug */,
-				E52F5A011E5C21890084B3E2 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		E52F5A021E5C21890084B3E2 /* Build configuration list for PBXNativeTarget "camerademo" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				E52F5A031E5C21890084B3E2 /* Debug */,
-				E52F5A041E5C21890084B3E2 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-		};
-/* End XCConfigurationList section */
-	};
-	rootObject = E52F59E31E5C21890084B3E2 /* Project object */;
-}
diff --git a/camerademo/camerademo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate b/camerademo/camerademo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 3f97b50..0000000
--- a/camerademo/camerademo.xcodeproj/project.xcworkspace/xcuserdata/WindShan.xcuserdatad/UserInterfaceState.xcuserstate
+++ /dev/null
Binary files differ
diff --git a/camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/camerademo.xcscheme b/camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/camerademo.xcscheme
deleted file mode 100644
index b422b1d..0000000
--- a/camerademo/camerademo.xcodeproj/xcuserdata/WindShan.xcuserdatad/xcschemes/camerademo.xcscheme
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "0820"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-      </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>
diff --git a/camerademo/camerademo/Base.lproj/Main.storyboard b/camerademo/camerademo/Base.lproj/Main.storyboard
deleted file mode 100644
index 4529698..0000000
--- a/camerademo/camerademo/Base.lproj/Main.storyboard
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
-    <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--View Controller-->
-        <scene sceneID="tne-QT-ifu">
-            <objects>
-                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
-                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
-            </objects>
-        </scene>
-    </scenes>
-</document>
diff --git a/camerademo/camerademo/demo/FileManager/MPFileManager.h b/camerademo/camerademo/demo/FileManager/MPFileManager.h
deleted file mode 100755
index 15562d4..0000000
--- a/camerademo/camerademo/demo/FileManager/MPFileManager.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-//  MPFileManager.h
-//  MobileProject ���������������
-//
-//  Created by wujunyang on 16/7/22.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <AssetsLibrary/ALAsset.h>
-#import <AssetsLibrary/ALAssetsLibrary.h>
-#import <AssetsLibrary/ALAssetsGroup.h>
-#import <AssetsLibrary/ALAssetRepresentation.h>
-
-@interface MPFileManager : NSObject
-
-+ (MPFileManager *)sharedManager;
-
-//������������������
-+ (NSString *)downloadPath;
-//������������������
-+ (NSString *)uploadPath;
-
-//���������������������APP������������
-+ (BOOL)writeUploadDataWithName:(NSString *)fileName andAsset:(ALAsset *)asset;
-//���������������������APP������������
-+ (BOOL)writeUploadDataWithName:(NSString *)fileName andImage:(UIImage *)image;
-//������APP���������������������
-+ (BOOL)deleteUploadDataWithName:(NSString *)fileName;
-
-@end
diff --git a/camerademo/camerademo/demo/FileManager/MPFileManager.m b/camerademo/camerademo/demo/FileManager/MPFileManager.m
deleted file mode 100755
index f514428..0000000
--- a/camerademo/camerademo/demo/FileManager/MPFileManager.m
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-//  MPFileManager.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/22.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "MPFileManager.h"
-
-@implementation MPFileManager
-
-+ (MPFileManager *)sharedManager {
-    static MPFileManager *_sharedManager = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        _sharedManager = [[MPFileManager alloc] init];
-    });
-    return _sharedManager;
-}
-
-- (instancetype)init
-{
-    self = [super init];
-    if (self) {
-        [[self class] createFolder:[[self class] downloadPath]];
-        [[self class] createFolder:[[self class] uploadPath]];
-    }
-    return self;
-}
-
-/**
- *  @author wujunyang, 16-07-22 11:07:41
- *
- *  @brief  ������������������
- *
- *  @return <#return value description#>
- */
-+ (NSString *)downloadPath{
-    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
-    NSString *downloadPath = [documentPath stringByAppendingPathComponent:@"MobileProject_Download"];
-    return downloadPath;
-}
-
-/**
- *  @author wujunyang, 16-07-22 11:07:58
- *
- *  @brief  ������������������
- *
- *  @return <#return value description#>
- */
-+ (NSString *)uploadPath{
-    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
-    NSString *uploadPath = [documentPath stringByAppendingPathComponent:@"MobileProject_Upload"];
-    return uploadPath;
-}
-
-/**
- *  @author wujunyang, 16-07-22 11:07:50
- *
- *  @brief  ���������������������
- *
- *  @param path <#path description#>
- *
- *  @return <#return value description#>
- */
-+ (BOOL)createFolder:(NSString *)path{
-    BOOL isDir = NO;
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    BOOL existed = [fileManager fileExistsAtPath:path isDirectory:&isDir];
-    BOOL isCreated = NO;
-    if (!(isDir == YES && existed == YES)){
-        isCreated = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-    }else{
-        isCreated = YES;
-    }
-    return isCreated;
-}
-
-
-+ (BOOL)writeUploadDataWithName:(NSString *)fileName andAsset:(ALAsset *)asset{
-    if (![self createFolder:[self uploadPath]]) {
-        return NO;
-    }
-    NSString *filePath = [[self uploadPath] stringByAppendingPathComponent:fileName];
-    
-    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
-    NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
-    if (!handle) {
-        return NO;
-    }
-    static const NSUInteger BufferSize = 1024*1024;
-    
-    ALAssetRepresentation *rep = [asset defaultRepresentation];
-    uint8_t *buffer = calloc(BufferSize, sizeof(*buffer));
-    NSUInteger offset = 0, bytesRead = 0;
-    
-    do {
-        @try {
-            bytesRead = [rep getBytes:buffer fromOffset:offset length:BufferSize error:nil];
-            [handle writeData:[NSData dataWithBytesNoCopy:buffer length:bytesRead freeWhenDone:NO]];
-            offset += bytesRead;
-        } @catch (NSException *exception) {
-            free(buffer);
-            
-            return NO;
-        }
-    } while (bytesRead > 0);
-    
-    free(buffer);
-    return YES;
-}
-
-+ (BOOL)writeUploadDataWithName:(NSString *)fileName andImage:(UIImage *)image{
-    if (![self createFolder:[self uploadPath]]) {
-        return NO;
-    }
-    NSString *filePath = [[self uploadPath] stringByAppendingPathComponent:fileName];
-    
-    return [UIImageJPEGRepresentation(image, 1.0) writeToFile:filePath options:NSAtomicWrite error:nil];
-}
-
-+ (BOOL)deleteUploadDataWithName:(NSString *)fileName{
-    NSString *filePath = [[self uploadPath] stringByAppendingPathComponent:fileName];
-    NSFileManager *fm = [NSFileManager defaultManager];
-    if ([fm fileExistsAtPath:filePath]) {
-        return [fm removeItemAtPath:filePath error:nil];
-    }else{
-        return YES;
-    }
-}
-
-@end
diff --git a/camerademo/camerademo/demo/MPUploadImageHelper.h b/camerademo/camerademo/demo/MPUploadImageHelper.h
deleted file mode 100755
index e752fb2..0000000
--- a/camerademo/camerademo/demo/MPUploadImageHelper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-//  MPUploadImageHelper.h
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "MPImageItemModel.h"
-
-@interface MPUploadImageHelper : NSObject
-
-//������������������imagesArray ���������selectedAssetURLs������������KVO������������
-@property (readwrite, nonatomic, strong) NSMutableArray *imagesArray;
-@property (readwrite, nonatomic, strong) NSMutableArray *selectedAssetURLs;
-
-
-- (void)addASelectedAssetURL:(NSURL *)assetURL;
-- (void)deleteASelectedAssetURL:(NSURL *)assetURL;
-- (void)deleteAImage:(MPImageItemModel *)imageInfo;
-
-/**
- *  @author wujunyang, 16-07-25 13:07:17
- *
- *  @brief  <#Description#>
- *
- *  @param isUploadProcess ������������������������YES���������������������
- *
- *  @return <#return value description#>
- */
-+(MPUploadImageHelper *)MPUploadImageForSend:(BOOL)isUploadProcess;
-
-@end
diff --git a/camerademo/camerademo/demo/MPUploadImageHelper.m b/camerademo/camerademo/demo/MPUploadImageHelper.m
deleted file mode 100755
index 8cd4d65..0000000
--- a/camerademo/camerademo/demo/MPUploadImageHelper.m
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-//  MPUploadImageHelper.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "MPUploadImageHelper.h"
-
-@interface MPUploadImageHelper()
-@property(nonatomic)BOOL isUploadProcess;
-@end
-
-static MPUploadImageHelper *_mpUploadImageHelper = nil;
-
-@implementation MPUploadImageHelper
-
-+(MPUploadImageHelper *)MPUploadImageForSend:(BOOL)isUploadProcess
-{
-    _mpUploadImageHelper = [[MPUploadImageHelper alloc] init];
-    _mpUploadImageHelper.isUploadProcess=isUploadProcess;
-    return _mpUploadImageHelper;
-}
-
-- (void)setSelectedAssetURLs:(NSMutableArray *)selectedAssetURLs{
-    NSMutableArray *needToAdd = [NSMutableArray new];
-    NSMutableArray *needToDelete = [NSMutableArray new];
-    [self.selectedAssetURLs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
-        if (![selectedAssetURLs containsObject:obj]) {
-            [needToDelete addObject:obj];
-        }
-    }];
-    [needToDelete enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
-        [self deleteASelectedAssetURL:obj];
-    }];
-    [selectedAssetURLs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
-        if (![self.selectedAssetURLs containsObject:obj]) {
-            [needToAdd addObject:obj];
-        }
-    }];
-    [needToAdd enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
-        [self addASelectedAssetURL:obj];
-    }];
-}
-
-
-- (void)addASelectedAssetURL:(NSURL *)assetURL{
-    if (!_selectedAssetURLs) {
-        _selectedAssetURLs = [NSMutableArray new];
-    }
-    if (!_imagesArray) {
-        _imagesArray = [NSMutableArray new];
-    }
-    
-    [_selectedAssetURLs addObject:assetURL];
-    
-    NSMutableArray *imagesArray = [self mutableArrayValueForKey:@"imagesArray"];//������kvo
-    MPImageItemModel *imageItem = [MPImageItemModel imageWithAssetURL:assetURL isUploadProcess:self.isUploadProcess];
-    [imagesArray addObject:imageItem];
-}
-
-- (void)deleteASelectedAssetURL:(NSURL *)assetURL{
-    [self.selectedAssetURLs removeObject:assetURL];
-    NSMutableArray *imagesArray = [self mutableArrayValueForKey:@"imagesArray"];//������kvo
-    [imagesArray enumerateObjectsUsingBlock:^(MPImageItemModel *obj, NSUInteger idx, BOOL *stop) {
-        if (obj.assetURL == assetURL) {
-            [imagesArray removeObject:obj];
-            *stop = YES;
-        }
-    }];
-}
-
-- (void)deleteAImage:(MPImageItemModel *)imageInfo{
-    NSMutableArray *imagesArray = [self mutableArrayValueForKey:@"imagesArray"];//������kvo
-    [imagesArray removeObject:imageInfo];
-    if (imageInfo.assetURL) {
-        [self.selectedAssetURLs removeObject:imageInfo.assetURL];
-    }
-}
-
-@end
diff --git a/camerademo/camerademo/demo/MPUploadImagesViewController.h b/camerademo/camerademo/demo/MPUploadImagesViewController.h
deleted file mode 100755
index 1ed9601..0000000
--- a/camerademo/camerademo/demo/MPUploadImagesViewController.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-//  MPUploadImagesViewController.h
-//  MobileProject ������������
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-
-@interface MPUploadImagesViewController : UIViewController
-
-@end
diff --git a/camerademo/camerademo/demo/MPUploadImagesViewController.m b/camerademo/camerademo/demo/MPUploadImagesViewController.m
deleted file mode 100755
index 99c2a66..0000000
--- a/camerademo/camerademo/demo/MPUploadImagesViewController.m
+++ /dev/null
@@ -1,231 +0,0 @@
-//
-//  MPUploadImagesViewController.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "MPUploadImagesViewController.h"
-
-@interface MPUploadImagesViewController()<UITableViewDataSource, UITableViewDelegate,UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, QBImagePickerControllerDelegate>
-@property (nonatomic,strong) UITableView         *myTableView;
-@property (strong, nonatomic) MPUploadImageHelper *curUploadImageHelper;
-@end
-
-
-@implementation MPUploadImagesViewController
-
-
-- (void)viewDidLoad {
-    [super viewDidLoad];
-    self.view.backgroundColor=[UIColor whiteColor];
-    self.navigationItem.title=@"������������";
-    
-    //���������
-    _curUploadImageHelper=[MPUploadImageHelper MPUploadImageForSend:NO];
-    
-    //���������������
-    if (!_myTableView) {
-        _myTableView  = [[UITableView alloc] initWithFrame:CGRectMake(0,0, Main_Screen_Width, Main_Screen_Height) style:UITableViewStylePlain];
-        _myTableView.tableFooterView=[UIView new];
-        _myTableView.showsVerticalScrollIndicator   = NO;
-        _myTableView.showsHorizontalScrollIndicator = NO;
-        _myTableView.dataSource                     = self;
-        _myTableView.delegate                       = self;
-        [_myTableView registerClass:[MPImageUploadCell class] forCellReuseIdentifier:NSStringFromClass([MPImageUploadCell class])];
-        [self.view addSubview:_myTableView];
-        [_myTableView mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.edges.equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
-        }];
-    }
-    
-    //������������
-    UIButton*rightButton = [[UIButton alloc]initWithFrame:CGRectMake(0,0,70,30)];
-    [rightButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
-    [rightButton setTitle:@"������" forState:UIControlStateNormal];
-    [rightButton addTarget:self action:@selector(myAction)forControlEvents:UIControlEventTouchUpInside];
-    UIBarButtonItem*rightItem = [[UIBarButtonItem alloc]initWithCustomView:rightButton];
-    self.navigationItem.rightBarButtonItem= rightItem;
-}
-
-- (void)didReceiveMemoryWarning {
-    [super didReceiveMemoryWarning];
-}
-
-
-- (void)dealloc
-{
-    _myTableView.delegate = nil;
-    _myTableView.dataSource = nil;
-}
-
-#pragma mark UITableViewDataSource, UITableViewDelegate������������
-
--(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
-    return 1;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-    return 1;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    MPImageUploadCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([MPImageUploadCell class]) forIndexPath:indexPath];
-    __weak typeof(self)weakSelf = self;
-    cell.accessoryType    = UITableViewCellAccessoryNone;
-    cell.curUploadImageHelper=self.curUploadImageHelper;
-    cell.addPicturesBlock = ^(){
-        [weakSelf showActionForPhoto];
-    };
-    cell.deleteImageBlock = ^(MPImageItemModel *toDelete)
-    {
-        [weakSelf.curUploadImageHelper deleteAImage:toDelete];
-        [weakSelf.myTableView reloadData];
-    };
-    return cell;
-}
-
-- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
-    return [MPImageUploadCell cellHeightWithObj:self.curUploadImageHelper];
-}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
-    [tableView deselectRowAtIndexPath:indexPath animated:YES];
-}
-
-
-#pragma mark UIActionSheetDelegate
-
-- (void)actionSheet:(UIActionSheet *)modalView clickedButtonAtIndex:(NSInteger)buttonIndex
-{
-    if (buttonIndex == 0)
-    {
-        //������
-        if (![cameraHelper checkCameraAuthorizationStatus]) {
-            return;
-        }
-        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
-        picker.delegate = self;
-        picker.allowsEditing = NO;//���������������
-        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
-        [self presentViewController:picker animated:YES completion:nil];//������������������
-    }else if (buttonIndex == 1)
-    {
-        //������
-        if (![cameraHelper checkPhotoLibraryAuthorizationStatus]) {
-            return;
-        }
-        QBImagePickerController *imagePickerController = [[QBImagePickerController alloc] init];
-        [imagePickerController.selectedAssetURLs removeAllObjects];
-        [imagePickerController.selectedAssetURLs addObjectsFromArray:self.curUploadImageHelper.selectedAssetURLs];
-        imagePickerController.filterType = QBImagePickerControllerFilterTypePhotos;
-        imagePickerController.delegate = self;
-        imagePickerController.maximumNumberOfSelection = kupdateMaximumNumberOfImage;
-        imagePickerController.allowsMultipleSelection = YES;
-        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:imagePickerController];
-        [self presentViewController:navigationController animated:YES completion:NULL];
-    }
-}
-
-
-#pragma mark UIImagePickerControllerDelegate
-
-- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
-{
-    UIImage *pickerImage = [info objectForKey:UIImagePickerControllerOriginalImage];
-    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
-    [assetsLibrary writeImageToSavedPhotosAlbum:[pickerImage CGImage] orientation:(ALAssetOrientation)pickerImage.imageOrientation completionBlock:^(NSURL *assetURL, NSError *error) {
-        [self.curUploadImageHelper addASelectedAssetURL:assetURL];
-        //������������ ������������������������
-        [self partialTableViewRefresh];
-    }];
-    [picker dismissViewControllerAnimated:YES completion:^{}];
-}
-
-- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
-{
-    [picker dismissViewControllerAnimated:YES completion:nil];
-}
-
-
-#pragma mark UINavigationControllerDelegate, QBImagePickerControllerDelegate
-
-- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didSelectAssets:(NSArray *)assets{
-    NSMutableArray *selectedAssetURLs = [NSMutableArray new];
-    [imagePickerController.selectedAssetURLs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
-        [selectedAssetURLs addObject:obj];
-    }];
-    MPWeakSelf(self)
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-        self.curUploadImageHelper.selectedAssetURLs = selectedAssetURLs;
-        dispatch_async(dispatch_get_main_queue(), ^{
-            MPStrongSelf(self)
-            //������������ ������������������������
-            [self partialTableViewRefresh];
-        });
-    });
-    [self dismissViewControllerAnimated:YES completion:nil];
-}
-- (void)qb_imagePickerControllerDidCancel:(QBImagePickerController *)imagePickerController{
-    [self dismissViewControllerAnimated:YES completion:nil];
-}
-
-#pragma mark ���������������
-
-//���������������
--(void)showActionForPhoto
-{
-    UIActionSheet *actionSheet = [[UIActionSheet alloc]
-                                  initWithTitle:nil
-                                  delegate:self
-                                  cancelButtonTitle:@"������"
-                                  destructiveButtonTitle:nil
-                                  otherButtonTitles:@"������",@"���������������",nil];
-    actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
-    [actionSheet showInView:self.view];
-}
-
-//��������������������������������� ������������������������
--(void)partialTableViewRefresh
-{
-    [self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
-}
-
-//������������
--(void)myAction
-{
-    if (self.curUploadImageHelper.selectedAssetURLs.count==0) {
-        [MBProgressHUD showAutoMessage:@"���������������������������" ToView:nil];
-        return;
-    }
-    
-    MPUploadImageService *req=[[MPUploadImageService alloc]initWithUploadImages:self.curUploadImageHelper];
-    
-    [req startWithCompletionBlockWithSuccess:^(__kindof YTKBaseRequest *request) {
-        //������������������������������
-        
-    } failure:^(__kindof YTKBaseRequest *request) {
-        [MPRequstFailedHelper requstFailed:request];
-    }];
-    
-    //������������
-    MPWeakSelf(self)
-    req.uploadPropressBlock = ^(NSUInteger __unused bytesWritten,
-                                     long long totalBytesWritten,
-                                     long long totalBytesExpectedToWrite)
-    {
-        
-        MPStrongSelf(self);
-        CGFloat propress = totalBytesWritten*1.0/totalBytesExpectedToWrite;
-        NSLog(@"���������������%lld/%lld___%2f",totalBytesWritten,totalBytesExpectedToWrite,propress);
-        dispatch_async(dispatch_get_main_queue(), ^{
-            //������UI
-        });
-        
-        
-    };
-}
-@end
diff --git a/camerademo/camerademo/demo/Model/MPImageItemModel.h b/camerademo/camerademo/demo/Model/MPImageItemModel.h
deleted file mode 100755
index a23da37..0000000
--- a/camerademo/camerademo/demo/Model/MPImageItemModel.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-//  MPImageItemModel.h
-//  MobileProject ������������������������
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "MPFileManager.h"
-#import "imageCompressHelper.h"
-#import "dateTimeHelper.h"
-#import "UIImage+Resize.h"
-#import "UIImage+FX.h"
-
-typedef NS_ENUM(NSInteger, MPImageUploadState)
-{
-    MPImageUploadStateInit = 0,
-    MPImageUploadStateIng,
-    MPImageUploadStateSuccess,
-    MPImageUploadStateFail
-};
-
-
-@interface MPImageItemModel : NSObject
-
-//������ ���������
-@property (readwrite, nonatomic, strong) UIImage *image, *thumbnailImage;
-//������������asstURL
-@property (strong, nonatomic) NSURL *assetURL;
-//������������
-@property (assign, nonatomic) MPImageUploadState uploadState;
-//���������������������[���������������������������������������������������������������������������������������������������,������������]
-@property(nonatomic,copy)NSString *httpUrl;
-@property(nonatomic,copy)NSString *upServicePath;
-//������������������ ������������ ��������� ������������
-@property (readwrite, nonatomic, strong) NSString *photoName;
-@property (readwrite, nonatomic, strong) NSString *photoLatitude;
-@property (readwrite, nonatomic, strong) NSString *photoLongitude;
-@property (readwrite, nonatomic, strong) NSString *photoTime;
-
-//������������
-+ (instancetype)imageWithAssetURL:(NSURL *)assetURL isUploadProcess:(BOOL)isUploadProcess;
-+ (instancetype)imageWithAssetURL:(NSURL *)assetURL andImage:(UIImage *)image;
-
-@end
diff --git a/camerademo/camerademo/demo/Model/MPImageItemModel.m b/camerademo/camerademo/demo/Model/MPImageItemModel.m
deleted file mode 100755
index 2d0bc80..0000000
--- a/camerademo/camerademo/demo/Model/MPImageItemModel.m
+++ /dev/null
@@ -1,100 +0,0 @@
-//
-//  MPImageItemModel.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "MPImageItemModel.h"
-#import <CoreLocation/CoreLocation.h>
-
-@implementation MPImageItemModel
-
-+ (instancetype)imageWithAssetURL:(NSURL *)assetURL isUploadProcess:(BOOL)isUploadProcess{
-    MPImageItemModel *imageItem = [[MPImageItemModel alloc] init];
-    imageItem.uploadState = MPImageUploadStateInit;
-    imageItem.assetURL = assetURL;
-    
-    MPWeakSelf(self);
-    
-    void (^selectAsset)(ALAsset *) = ^(ALAsset *asset){
-        if (asset) {
-            UIImage *highQualityImage = [imageCompressHelper fullScreenImageALAsset:asset];
-            UIImage *thumbnailImage = [UIImage imageWithCGImage:[asset thumbnail]];
-            
-            //������������
-            MPStrongSelf(self);
-            [self imageInfoWithALAsset:asset imageItem:imageItem];
-            
-            dispatch_async(dispatch_get_main_queue(), ^{
-                imageItem.image = [imageCompressHelper compressedImageToLimitSizeOfKB:100 image:highQualityImage];;
-                imageItem.thumbnailImage = thumbnailImage;
-                
-                if (isUploadProcess) {
-                    //���������������  ���������������������������������
-                    [MPFileManager writeUploadDataWithName:imageItem.photoName andImage:imageItem.image];
-                }
-            });
-        }
-    };
-    
-    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
-    MPWeakSelf(assetsLibrary);
-    [assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
-        if (asset) {
-            selectAsset(asset);
-        }else{
-            MPStrongSelf(assetsLibrary);
-            [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupPhotoStream usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
-                [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopG) {
-                    if([result.defaultRepresentation.url isEqual:assetURL]) {
-                        selectAsset(result);
-                        *stop = YES;
-                        *stopG = YES;
-                    }
-                }];
-            } failureBlock:^(NSError *error) {
-                NSLog(@"������������������");
-            }];
-        }
-    }failureBlock:^(NSError *error) {
-        NSLog(@"������������������");
-    }];
-    return imageItem;
-    
-}
-
-//������������������������
-+(void)imageInfoWithALAsset:(ALAsset *)asset imageItem:(MPImageItemModel *)imageItem
-{
-    //������������
-    NSDate * nsALAssetPropertyDate = [ asset valueForProperty:ALAssetPropertyDate ];
-    if (nsALAssetPropertyDate!=nil) {
-        imageItem.photoTime=[dateTimeHelper htcTimeToLocationStr:nsALAssetPropertyDate];
-    }
-    
-    //GPS������
-    CLLocation *location = [asset valueForProperty:ALAssetPropertyLocation];
-    if (location) {
-        CLLocationCoordinate2D curCoordinate=location.coordinate;
-        imageItem.photoLatitude=[NSString stringWithFormat:@"%f",curCoordinate.latitude];
-        imageItem.photoLongitude=[NSString stringWithFormat:@"%f",curCoordinate.longitude];
-    }
-    
-    //������������
-    ALAssetRepresentation *representation = [asset defaultRepresentation];
-    imageItem.photoName = [representation filename];
-}
-
-
-+ (instancetype)imageWithAssetURL:(NSURL *)assetURL andImage:(UIImage *)image{
-    MPImageItemModel *imageItem = [[MPImageItemModel alloc] init];
-    imageItem.uploadState = MPImageUploadStateInit;
-    imageItem.assetURL = assetURL;
-    imageItem.image = image;
-    imageItem.thumbnailImage = [image imageScaledToSize:CGSizeMake(AdaptedWidth(70), AdaptedWidth(70))];
-    return imageItem;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/UITapImageView.h b/camerademo/camerademo/demo/OtherHelper/UITapImageView.h
deleted file mode 100755
index 3d3233b..0000000
--- a/camerademo/camerademo/demo/OtherHelper/UITapImageView.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-//  UITapImageView.h
-//  zxptUser
-//
-//  Created by wujunyang on 16/6/8.
-//  Copyright �� 2016��� qijia. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UITapImageView : UIImageView
-
-- (void)addTapBlock:(void(^)(id obj))tapAction;
-
--(void)setImageWithUrl:(NSURL *)imgUrl placeholderImage:(UIImage *)placeholderImage tapBlock:(void(^)(id obj))tapAction;
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/UITapImageView.m b/camerademo/camerademo/demo/OtherHelper/UITapImageView.m
deleted file mode 100755
index 4193a43..0000000
--- a/camerademo/camerademo/demo/OtherHelper/UITapImageView.m
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-//  UITapImageView.m
-//  zxptUser
-//
-//  Created by wujunyang on 16/6/8.
-//  Copyright �� 2016��� qijia. All rights reserved.
-//
-
-#import "UITapImageView.h"
-
-@interface  UITapImageView ()
-
-@property (nonatomic, copy) void(^tapAction)(id);
-
-@end
-
-@implementation UITapImageView
-
-- (id)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    if (self) {
-        // Initialization code
-    }
-    return self;
-}
-
-- (instancetype)init
-{
-    return [self initWithFrame:CGRectZero];
-}
-
-- (void)tap{
-    if (self.tapAction) {
-        self.tapAction(self);
-    }
-}
-- (void)addTapBlock:(void(^)(id obj))tapAction{
-    self.tapAction = tapAction;
-    if (![self gestureRecognizers]) {
-        self.userInteractionEnabled = YES;
-        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
-        [self addGestureRecognizer:tap];
-    }
-}
-
--(void)setImageWithUrl:(NSURL *)imgUrl placeholderImage:(UIImage *)placeholderImage tapBlock:(void(^)(id obj))tapAction{
-    [self sd_setImageWithURL:imgUrl placeholderImage:placeholderImage];
-    [self addTapBlock:tapAction];
-}
-
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/cameraHelper.h b/camerademo/camerademo/demo/OtherHelper/cameraHelper.h
deleted file mode 100755
index 609027f..0000000
--- a/camerademo/camerademo/demo/OtherHelper/cameraHelper.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-//  cameraHelper.h
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface cameraHelper : NSObject
-
-/**
- * ������������"������"������������, ���������������������, ������������������������������������.
- */
-+ (BOOL)checkPhotoLibraryAuthorizationStatus;
-
-/**
- * ������������"������"������������, ���������������������, ������������������������������������.
- */
-+ (BOOL)checkCameraAuthorizationStatus;
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/cameraHelper.m b/camerademo/camerademo/demo/OtherHelper/cameraHelper.m
deleted file mode 100755
index 73a9a94..0000000
--- a/camerademo/camerademo/demo/OtherHelper/cameraHelper.m
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-//  cameraHelper.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "cameraHelper.h"
-#import <AssetsLibrary/ALAsset.h>
-#import <AssetsLibrary/ALAssetsLibrary.h>
-#import <AssetsLibrary/ALAssetsGroup.h>
-#import <AssetsLibrary/ALAssetRepresentation.h>
-
-@import AVFoundation;
-
-@implementation cameraHelper
-
-+ (BOOL)checkPhotoLibraryAuthorizationStatus
-{
-    //if ([ALAssetsLibrary respondsToSelector:@selector(authorizationStatus)]) {
-        ALAuthorizationStatus authStatus = [ALAssetsLibrary authorizationStatus];
-            if (ALAuthorizationStatusDenied == authStatus ||
-                ALAuthorizationStatusRestricted == authStatus) {
-                [MBProgressHUD showAutoMessage:@"������iPhone������������->������->������������������������������������������" ToView:nil];
-                return NO;
-        //    }
-        }
-    return YES;
-}
-
-+ (BOOL)checkCameraAuthorizationStatus
-{
-    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
-        [MBProgressHUD showAutoMessage:@"������������������������" ToView:nil];
-        return NO;
-    }
-
-    if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) {
-        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
-        if (AVAuthorizationStatusDenied == authStatus ||
-            AVAuthorizationStatusRestricted == authStatus) {
-            [MBProgressHUD showAutoMessage:@"������iPhone������������->������->������������������������������������������" ToView:nil];
-            return NO;
-        }
-    }
-    return YES;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.h b/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.h
deleted file mode 100755
index 7e25da9..0000000
--- a/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-//  dateTimeHelper.h
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface dateTimeHelper : NSObject
-
-//������������������������������
-+ (NSString *)htcTimeToLocationStr:(NSDate*)curDate;
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.m b/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.m
deleted file mode 100755
index 0cb4e18..0000000
--- a/camerademo/camerademo/demo/OtherHelper/dateTimeHelper.m
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-//  dateTimeHelper.m
-//  MobileProject
-//
-//  Created by wujunyang on 16/7/20.
-//  Copyright �� 2016��� wujunyang. All rights reserved.
-//
-
-#import "dateTimeHelper.h"
-
-@implementation dateTimeHelper
-
-+ (NSString *)htcTimeToLocationStr:(NSDate*)curDate
-{
-    if (curDate==nil) {
-        return @"";
-    }
-    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc]init];
-    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
-    NSString *fixString = [dateFormatter stringFromDate:curDate];
-    return fixString;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.h b/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.h
deleted file mode 100755
index e94a550..0000000
--- a/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-//  imageCompressHelper.h
-//  zxptUser ������������
-//
-//  Created by wujunyang on 16/4/14.
-//  Copyright �� 2016��� qijia. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <AssetsLibrary/ALAsset.h>
-#import <AssetsLibrary/ALAssetsLibrary.h>
-#import <AssetsLibrary/ALAssetsGroup.h>
-#import <AssetsLibrary/ALAssetRepresentation.h>
-
-@interface imageCompressHelper : NSObject
-
-/**
- *  @author wujunyang, 16-04-14 15:04:54
- *
- *  @brief  ������������������KB���������������
- *
- *  @param kb    <#kb description#>
- *  @param image <#image description#>
- *
- *  @return <#return value description#>
- */
-+(UIImage*)compressedImageToLimitSizeOfKB:(CGFloat)kb image:(UIImage*)image;
-
-+(NSData*)returnDataCompressedImageToLimitSizeOfKB:(CGFloat)kb image:(UIImage*)image;
-
-//��������������������� ���������������������
-+(UIImage*) circleImage:(UIImage*) image withParam:(CGFloat) inset;
-
-//���������������������������
-+(UIImage *) imageCompressForWidth:(UIImage *)sourceImage targetWidth:(CGFloat)defineWidth;
-
-//���������������,size ������������������������ ������������ CGSizeMake(300, 140)
-+(UIImage *)compressImage:(UIImage *)sourceImage toTargetWidth:(CGFloat)targetWidth;
-
-//������������������
-+ (UIImage *)fullScreenImageALAsset:(ALAsset *)asset;
-@end
diff --git a/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.m b/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.m
deleted file mode 100755
index 2852c6a..0000000
--- a/camerademo/camerademo/demo/OtherHelper/imageCompressHelper.m
+++ /dev/null
@@ -1,163 +0,0 @@
-//
-//  imageCompressHelper.m
-//  zxptUser
-//
-//  Created by wujunyang on 16/4/14.
-//  Copyright �� 2016��� qijia. All rights reserved.
-//
-
-#import "imageCompressHelper.h"
-
-@implementation imageCompressHelper
-
-+(UIImage*)compressedImageToLimitSizeOfKB:(CGFloat)kb image:(UIImage*)image
-{
-    //������������kb���������������������
-    long imagePixel = CGImageGetWidth(image.CGImage)*CGImageGetHeight(image.CGImage);
-    long imageKB = imagePixel * CGImageGetBitsPerPixel(image.CGImage) / (8 * 1024);
-    if (imageKB > kb){
-        float compressedParam = kb / imageKB;
-        return [UIImage imageWithData:UIImageJPEGRepresentation(image, compressedParam)];
-    }
-    //������������
-    else{
-        return image;
-    }
-}
-
-+(NSData*)returnDataCompressedImageToLimitSizeOfKB:(CGFloat)kb image:(UIImage*)image
-{
-    //������������kb���������������������
-    long imagePixel = CGImageGetWidth(image.CGImage)*CGImageGetHeight(image.CGImage);
-    long imageKB = imagePixel * CGImageGetBitsPerPixel(image.CGImage) / (8 * 1024);
-    if (imageKB > kb){
-        float compressedParam = kb / imageKB;
-        return UIImageJPEGRepresentation(image, compressedParam);
-    }
-    //������������
-    else{
-        return UIImageJPEGRepresentation(image, 1);
-    }
-}
-
-
-+(UIImage*) circleImage:(UIImage*) image withParam:(CGFloat) inset
-{
-    //UIGraphicsBeginImageContext(image.size);
-    //������������ ���������������
-    UIGraphicsBeginImageContextWithOptions(image.size, NO, [[UIScreen mainScreen] scale]);
-    CGContextRef context =UIGraphicsGetCurrentContext();
-    
-    //���������������������2������������������
-    
-    CGContextSetLineWidth(context,2);
-    
-    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
-    
-    CGRect rect = CGRectMake(inset, inset, image.size.width - inset *2.0f, image.size.height - inset *2.0f);
-    
-    CGContextAddEllipseInRect(context, rect);
-    
-    CGContextClip(context);
-    
-    //���������������������image������
-    
-    [image drawInRect:rect];
-    
-    CGContextAddEllipseInRect(context, rect);
-    
-    CGContextStrokePath(context);
-    
-    //������������image
-    
-    UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext();
-    
-    UIGraphicsEndImageContext();
-    
-    return newimg;
-}
-
-+(UIImage *) imageCompressForWidth:(UIImage *)sourceImage targetWidth:(CGFloat)defineWidth
-{
-    UIImage *newImage = nil;
-    CGSize imageSize = sourceImage.size;
-    CGFloat width = imageSize.width;
-    CGFloat height = imageSize.height;
-    CGFloat targetWidth = defineWidth;
-    CGFloat targetHeight = height / (width / targetWidth);
-    CGSize size = CGSizeMake(targetWidth, targetHeight);
-    CGFloat scaleFactor = 0.0;
-    CGFloat scaledWidth = targetWidth;
-    CGFloat scaledHeight = targetHeight;
-    CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
-    
-    if(CGSizeEqualToSize(imageSize, size) == NO){
-        
-        CGFloat widthFactor = targetWidth / width;
-        CGFloat heightFactor = targetHeight / height;
-        
-        if(widthFactor > heightFactor){
-            scaleFactor = widthFactor;
-        }
-        else{
-            scaleFactor = heightFactor;
-        }
-        scaledWidth = width * scaleFactor;
-        scaledHeight = height * scaleFactor;
-        
-        if(widthFactor > heightFactor){
-            
-            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
-            
-        }else if(widthFactor < heightFactor){
-            
-            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
-        }
-    }
-    
-    UIGraphicsBeginImageContext(size);
-    
-    CGRect thumbnailRect = CGRectZero;
-    thumbnailRect.origin = thumbnailPoint;
-    thumbnailRect.size.width = scaledWidth;
-    thumbnailRect.size.height = scaledHeight;
-    
-    [sourceImage drawInRect:thumbnailRect];
-    
-    newImage = UIGraphicsGetImageFromCurrentImageContext();
-    
-    if(newImage == nil){
-        
-        NSLog(@"scale image fail");
-    }
-    UIGraphicsEndImageContext();
-    return newImage;
-}
-
-
-+(UIImage *)compressImage:(UIImage *)sourceImage toTargetWidth:(CGFloat)targetWidth
-{
-    CGSize imageSize = sourceImage.size;
-    
-    CGFloat width = imageSize.width;
-    CGFloat height = imageSize.height;
-    
-    CGFloat targetHeight = (targetWidth / width) * height;
-    
-    UIGraphicsBeginImageContext(CGSizeMake(targetWidth, targetHeight));
-    [sourceImage drawInRect:CGRectMake(0, 0, targetWidth, targetHeight)];
-    
-    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    
-    return newImage;
-}
-
-
-+ (UIImage *)fullScreenImageALAsset:(ALAsset *)asset{
-    ALAssetRepresentation *assetRep = [asset defaultRepresentation];
-    CGImageRef imgRef = [assetRep fullScreenImage];//fullScreenImage������������������������
-    UIImage *img = [UIImage imageWithCGImage:imgRef];
-    return img;
-}
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.h
deleted file mode 100755
index 161379c..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-//  QBAssetsCollectionCheckmarkView.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2014/01/01.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface QBAssetsCollectionCheckmarkView : UIView
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.m
deleted file mode 100755
index 82ee42d..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionCheckmarkView.m
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-//  QBAssetsCollectionCheckmarkView.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2014/01/01.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionCheckmarkView.h"
-
-@implementation QBAssetsCollectionCheckmarkView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        // View settings
-        self.backgroundColor = [UIColor clearColor];
-    }
-    
-    return self;
-}
-
-- (CGSize)sizeThatFits:(CGSize)size
-{
-    return CGSizeMake(24.0, 24.0);
-}
-
-- (void)drawRect:(CGRect)rect
-{
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    // Border
-    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
-    CGContextFillEllipseInRect(context, self.bounds);
-    
-    // Body
-    CGContextSetRGBFillColor(context, 20.0/255.0, 111.0/255.0, 223.0/255.0, 1.0);
-    CGContextFillEllipseInRect(context, CGRectInset(self.bounds, 1.0, 1.0));
-    
-    // Checkmark
-    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
-    CGContextSetLineWidth(context, 1.2);
-    
-    CGContextMoveToPoint(context, 6.0, 12.0);
-    CGContextAddLineToPoint(context, 10.0, 16.0);
-    CGContextAddLineToPoint(context, 18.0, 8.0);
-    
-    CGContextStrokePath(context);
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.h
deleted file mode 100755
index 630307c..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-//  QBAssetsCollectionFooterView.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface QBAssetsCollectionFooterView : UICollectionReusableView
-
-@property (nonatomic, strong, readonly) UILabel *textLabel;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.m
deleted file mode 100755
index 3d23af8..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionFooterView.m
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-//  QBAssetsCollectionFooterView.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionFooterView.h"
-
-@interface QBAssetsCollectionFooterView ()
-
-@property (nonatomic, strong, readwrite) UILabel *textLabel;
-
-@end
-
-@implementation QBAssetsCollectionFooterView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        // Create a label
-        UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-        textLabel.font = [UIFont systemFontOfSize:17];
-        textLabel.textColor = [UIColor blackColor];
-        textLabel.textAlignment = NSTextAlignmentCenter;
-        
-        [self addSubview:textLabel];
-        self.textLabel = textLabel;
-    }
-    
-    return self;
-}
-
-- (void)layoutSubviews
-{
-    [super layoutSubviews];
-    
-    // Layout text label
-    self.textLabel.frame = CGRectMake(0,
-                                      (self.bounds.size.height - 21.0) / 2.0,
-                                      self.bounds.size.width,
-                                      21.0);
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.h
deleted file mode 100755
index b4b5b39..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-//  QBAssetsCollectionOverlayView.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2014/01/01.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface QBAssetsCollectionOverlayView : UIView
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.m
deleted file mode 100755
index caa7ae6..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionOverlayView.m
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-//  QBAssetsCollectionOverlayView.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2014/01/01.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionOverlayView.h"
-#import <QuartzCore/QuartzCore.h>
-
-// Views
-#import "QBAssetsCollectionCheckmarkView.h"
-
-@interface QBAssetsCollectionOverlayView ()
-
-@property (nonatomic, strong) QBAssetsCollectionCheckmarkView *checkmarkView;
-
-@end
-
-@implementation QBAssetsCollectionOverlayView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        // View settings
-        self.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.4];
-        
-        // Create a checkmark view
-        QBAssetsCollectionCheckmarkView *checkmarkView = [[QBAssetsCollectionCheckmarkView alloc] initWithFrame:CGRectMake(self.bounds.size.width - (4.0 + 24.0), self.bounds.size.height - (4.0 + 24.0), 24.0, 24.0)];
-        checkmarkView.autoresizingMask = UIViewAutoresizingNone;
-        
-        checkmarkView.layer.shadowColor = [[UIColor grayColor] CGColor];
-        checkmarkView.layer.shadowOffset = CGSizeMake(0, 0);
-        checkmarkView.layer.shadowOpacity = 0.6;
-        checkmarkView.layer.shadowRadius = 2.0;
-        
-        [self addSubview:checkmarkView];
-        self.checkmarkView = checkmarkView;
-    }
-    
-    return self;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.h
deleted file mode 100755
index 58a78dc..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-//  QBAssetsCollectionVideoIndicatorView.h
-//  QBImagePickerControllerDemo
-//
-//  Created by Katsuma Tanaka on 2014/08/07.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface QBAssetsCollectionVideoIndicatorView : UIView
-
-@property (nonatomic, assign) NSTimeInterval duration;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.m
deleted file mode 100755
index 4aba36c..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionVideoIndicatorView.m
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-//  QBAssetsCollectionVideoIndicatorView.m
-//  QBImagePickerControllerDemo
-//
-//  Created by Katsuma Tanaka on 2014/08/07.
-//  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionVideoIndicatorView.h"
-#import <QuartzCore/QuartzCore.h>
-
-@implementation QBAssetsCollectionVideoIndicatorView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        self.backgroundColor = [UIColor clearColor];
-        self.clipsToBounds = YES;
-    }
-    
-    return self;
-}
-
-
-#pragma mark - Accessors
-
-- (void)setDuration:(NSTimeInterval)duration
-{
-    _duration = duration;
-    
-    [self setNeedsDisplay];
-}
-
-
-#pragma mark - Drawing the View
-
-- (void)drawRect:(CGRect)rect
-{
-    // Draw linear gradient
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-    CGFloat colors[12] = {
-        0.0, 0.0, 0.0, 0.9,
-        0.0, 0.0, 0.0, 0.45,
-        0.0, 0.0, 0.0, 0.0
-    };
-    const CGFloat locations[] = { 0.0, 0.55, 1.0 };
-    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, 3);
-    CGColorSpaceRelease(colorSpace);
-    
-    CGPoint startPoint = CGPointMake(0, CGRectGetHeight(self.bounds));
-    CGPoint endPoint = CGPointMake(0, 0);
-    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation);
-    
-    CGGradientRelease(gradient);
-    
-    // Draw camera icon
-    CGSize cameraIconSize = CGSizeMake(14.0, 8.0);
-    CGRect cameraIconRect = CGRectMake(5.0, (CGRectGetHeight(self.bounds) - cameraIconSize.height) / 2.0, cameraIconSize.width, cameraIconSize.height);
-    [self drawCameraIconInRect:cameraIconRect];
-    
-    // Draw duration
-    NSInteger minutes = (NSInteger)(self.duration / 60.0);
-    NSInteger seconds = (NSInteger)ceil(self.duration - 60.0 * (double)minutes);
-    NSString *durationString = [NSString stringWithFormat:@"%02ld:%02ld", (long)minutes, (long)seconds];
-    
-    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
-    paragraphStyle.alignment = NSTextAlignmentRight;
-    
-    UIFont *durationFont = [UIFont systemFontOfSize:12.0];
-    
-    CGRect durationRect = CGRectMake(CGRectGetMaxX(cameraIconRect), 0, CGRectGetWidth(self.bounds) - CGRectGetMaxX(cameraIconRect), CGRectGetHeight(self.bounds));
-    durationRect = CGRectInset(durationRect, 5.0, (CGRectGetHeight(self.bounds) - durationFont.lineHeight) / 2.0);
-    
-    [durationString drawInRect:durationRect
-                withAttributes:@{
-                                 NSParagraphStyleAttributeName: [paragraphStyle copy],
-                                 NSFontAttributeName: durationFont,
-                                 NSForegroundColorAttributeName: [UIColor whiteColor]
-                                 }];
-}
-
-- (void)drawCameraIconInRect:(CGRect)rect
-{
-    [[UIColor whiteColor] setFill];
-    
-    // Draw triangle
-    CGRect triangleRect = CGRectMake(0, CGRectGetMinY(rect), ceil(CGRectGetHeight(rect) / 2.0), CGRectGetHeight(rect));
-    triangleRect.origin.x = CGRectGetMinX(rect) + CGRectGetWidth(rect) - CGRectGetWidth(triangleRect);
-    
-    UIBezierPath *trianglePath = [UIBezierPath bezierPath];
-    [trianglePath moveToPoint:CGPointMake(CGRectGetMinX(triangleRect) + CGRectGetWidth(triangleRect), CGRectGetMinY(triangleRect))];
-    [trianglePath addLineToPoint:CGPointMake(CGRectGetMinX(triangleRect) + CGRectGetWidth(triangleRect), CGRectGetMaxY(triangleRect))];
-    [trianglePath addLineToPoint:CGPointMake(CGRectGetMinX(triangleRect), CGRectGetMidY(triangleRect))];
-    [trianglePath closePath];
-    [trianglePath fill];
-    
-    // Draw rounded square
-    CGRect squareRect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect) - CGRectGetWidth(triangleRect) - 1.0, CGRectGetHeight(rect));
-    UIBezierPath *squarePath = [UIBezierPath bezierPathWithRoundedRect:squareRect cornerRadius:2.0];
-    [squarePath fill];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.h
deleted file mode 100755
index caba987..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-//  QBAssetsCollectionViewCell.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-
-@interface QBAssetsCollectionViewCell : UICollectionViewCell
-
-@property (nonatomic, strong) ALAsset *asset;
-@property (nonatomic, assign) BOOL showsOverlayViewWhenSelected;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.m
deleted file mode 100755
index 502dc93..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewCell.m
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-//  QBAssetsCollectionViewCell.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionViewCell.h"
-
-// Views
-#import "QBAssetsCollectionOverlayView.h"
-#import "QBAssetsCollectionVideoIndicatorView.h"
-
-@interface QBAssetsCollectionViewCell ()
-
-@property (nonatomic, strong) UIImageView *imageView;
-@property (nonatomic, strong) QBAssetsCollectionOverlayView *overlayView;
-@property (nonatomic, strong) QBAssetsCollectionVideoIndicatorView *videoIndicatorView;
-
-@property (nonatomic, strong) UIImage *blankImage;
-
-@end
-
-@implementation QBAssetsCollectionViewCell
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        self.showsOverlayViewWhenSelected = YES;
-        
-        // Create a image view
-        UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
-        imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-        
-        [self.contentView addSubview:imageView];
-        self.imageView = imageView;
-    }
-    
-    return self;
-}
-
-- (void)setSelected:(BOOL)selected
-{
-    [super setSelected:selected];
-    
-    // Show/hide overlay view
-    if (selected && self.showsOverlayViewWhenSelected) {
-        [self showOverlayView];
-    } else {
-        [self hideOverlayView];
-    }
-}
-
-
-#pragma mark - Overlay View
-
-- (void)showOverlayView
-{
-    [self hideOverlayView];
-    
-    QBAssetsCollectionOverlayView *overlayView = [[QBAssetsCollectionOverlayView alloc] initWithFrame:self.contentView.bounds];
-    overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-    
-    [self.contentView addSubview:overlayView];
-    self.overlayView = overlayView;
-}
-
-- (void)hideOverlayView
-{
-    if (self.overlayView) {
-        [self.overlayView removeFromSuperview];
-        self.overlayView = nil;
-    }
-}
-
-
-#pragma mark - Video Indicator View
-
-- (void)showVideoIndicatorView
-{
-    CGFloat height = 19.0;
-    CGRect frame = CGRectMake(0, CGRectGetHeight(self.bounds) - height, CGRectGetWidth(self.bounds), height);
-    QBAssetsCollectionVideoIndicatorView *videoIndicatorView = [[QBAssetsCollectionVideoIndicatorView alloc] initWithFrame:frame];
-    videoIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-    videoIndicatorView.duration = [[self.asset valueForProperty:ALAssetPropertyDuration] doubleValue];
-    
-    [self.contentView addSubview:videoIndicatorView];
-    self.videoIndicatorView = videoIndicatorView;
-}
-
-- (void)hideVideoIndicatorView
-{
-    if (self.videoIndicatorView) {
-        [self.videoIndicatorView removeFromSuperview];
-        self.videoIndicatorView = nil;
-    }
-}
-
-
-#pragma mark - Accessors
-
-- (void)setAsset:(ALAsset *)asset
-{
-    _asset = asset;
-    
-    // Update view
-    CGImageRef thumbnailImageRef = [asset thumbnail];
-    
-    if (thumbnailImageRef) {
-        self.imageView.image = [UIImage imageWithCGImage:thumbnailImageRef];
-    } else {
-        self.imageView.image = [self blankImage];
-    }
-    
-    // Show video indicator if the asset is video
-    if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
-        [self showVideoIndicatorView];
-    } else {
-        [self hideVideoIndicatorView];
-    }
-}
-
-- (UIImage *)blankImage
-{
-    if (_blankImage == nil) {
-        CGSize size = CGSizeMake(100.0, 100.0);
-        UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
-        
-        [[UIColor colorWithWhite:(240.0 / 255.0) alpha:1.0] setFill];
-        UIRectFill(CGRectMake(0, 0, size.width, size.height));
-        
-        _blankImage = UIGraphicsGetImageFromCurrentImageContext();
-        
-        UIGraphicsEndImageContext();
-    }
-    
-    return _blankImage;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.h
deleted file mode 100755
index 036e7f6..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-//  QBAssetsCollectionViewController.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-
-// ViewControllers
-#import "QBImagePickerController.h"
-
-@class QBAssetsCollectionViewController;
-
-@protocol QBAssetsCollectionViewControllerDelegate <NSObject>
-
-@optional
-- (void)assetsCollectionViewController:(QBAssetsCollectionViewController *)assetsCollectionViewController didSelectAsset:(ALAsset *)asset;
-- (void)assetsCollectionViewController:(QBAssetsCollectionViewController *)assetsCollectionViewController didDeselectAsset:(ALAsset *)asset;
-- (void)assetsCollectionViewControllerDidFinishSelection:(QBAssetsCollectionViewController *)assetsCollectionViewController;
-
-@end
-
-@interface QBAssetsCollectionViewController : UICollectionViewController <UICollectionViewDelegateFlowLayout>
-
-@property (nonatomic, weak) QBImagePickerController *imagePickerController;
-
-@property (nonatomic, weak) id<QBAssetsCollectionViewControllerDelegate> delegate;
-@property (nonatomic, strong) ALAssetsGroup *assetsGroup;
-@property (nonatomic, assign) QBImagePickerControllerFilterType filterType;
-@property (nonatomic, assign) BOOL allowsMultipleSelection;
-@property (nonatomic, assign) NSUInteger minimumNumberOfSelection;
-@property (nonatomic, assign) NSUInteger maximumNumberOfSelection;
-
-- (void)selectAssetHavingURL:(NSURL *)URL;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.m
deleted file mode 100755
index b3fc9c3..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewController.m
+++ /dev/null
@@ -1,344 +0,0 @@
-//
-//  QBAssetsCollectionViewController.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionViewController.h"
-
-// Views
-#import "QBAssetsCollectionViewCell.h"
-#import "QBAssetsCollectionFooterView.h"
-
-@interface QBAssetsCollectionViewController ()
-
-@property (nonatomic, strong) NSMutableArray *assets;
-
-@property (nonatomic, assign) NSUInteger numberOfAssets;
-@property (nonatomic, assign) NSUInteger numberOfPhotos;
-@property (nonatomic, assign) NSUInteger numberOfVideos;
-
-@property (nonatomic, assign) BOOL disableScrollToBottom;
-
-@end
-
-@implementation QBAssetsCollectionViewController
-
-- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout
-{
-    self = [super initWithCollectionViewLayout:layout];
-    
-    if (self) {
-        // View settings
-        self.collectionView.backgroundColor = [UIColor whiteColor];
-        
-        // Register cell class
-        [self.collectionView registerClass:[QBAssetsCollectionViewCell class]
-                forCellWithReuseIdentifier:@"AssetsCell"];
-        [self.collectionView registerClass:[QBAssetsCollectionFooterView class]
-                forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
-                       withReuseIdentifier:@"FooterView"];
-    }
-    
-    return self;
-}
-
-- (void)viewWillAppear:(BOOL)animated
-{
-    [super viewWillAppear:animated];
-    
-    // Scroll to bottom
-    if (self.isMovingToParentViewController && !self.disableScrollToBottom) {
-        CGFloat topInset;
-        if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) { // iOS7 or later
-            topInset = ((self.edgesForExtendedLayout && UIRectEdgeTop) && (self.collectionView.contentInset.top == 0)) ? (20.0 + 44.0) : 0.0;
-        } else {
-            topInset = (self.collectionView.contentInset.top == 0) ? (20.0 + 44.0) : 0.0;
-        }
-
-        [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.collectionViewLayout.collectionViewContentSize.height - self.collectionView.frame.size.height + topInset)
-                                     animated:NO];
-    }
-    
-    // Validation
-    if (self.allowsMultipleSelection) {
-        self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:self.imagePickerController.selectedAssetURLs.count];
-    }
-}
-
-- (void)viewWillDisappear:(BOOL)animated
-{
-    [super viewWillDisappear:animated];
-    
-    self.disableScrollToBottom = YES;
-}
-
-- (void)viewDidDisappear:(BOOL)animated
-{
-    [super viewDidDisappear:animated];
-    
-    self.disableScrollToBottom = NO;
-}
-
-
-#pragma mark - Accessors
-
-- (void)setFilterType:(QBImagePickerControllerFilterType)filterType
-{
-    _filterType = filterType;
-    
-    // Set assets filter
-    [self.assetsGroup setAssetsFilter:ALAssetsFilterFromQBImagePickerControllerFilterType(self.filterType)];
-}
-
-- (void)setAssetsGroup:(ALAssetsGroup *)assetsGroup
-{
-    _assetsGroup = assetsGroup;
-    
-    // Set title
-    self.title = [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName];
-    
-    // Set assets filter
-    [self.assetsGroup setAssetsFilter:ALAssetsFilterFromQBImagePickerControllerFilterType(self.filterType)];
-    
-    // Load assets
-    NSMutableArray *assets = [NSMutableArray array];
-    __block NSUInteger numberOfAssets = 0;
-    __block NSUInteger numberOfPhotos = 0;
-    __block NSUInteger numberOfVideos = 0;
-    
-    [self.assetsGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
-        if (result) {
-            numberOfAssets++;
-            
-            NSString *type = [result valueForProperty:ALAssetPropertyType];
-            if ([type isEqualToString:ALAssetTypePhoto]) numberOfPhotos++;
-            else if ([type isEqualToString:ALAssetTypeVideo]) numberOfVideos++;
-            
-            [assets addObject:result];
-        }
-    }];
-    
-    self.assets = assets;
-    self.numberOfAssets = numberOfAssets;
-    self.numberOfPhotos = numberOfPhotos;
-    self.numberOfVideos = numberOfVideos;
-    
-    // Update view
-    [self.collectionView reloadData];
-}
-
-- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection
-{
-    self.collectionView.allowsMultipleSelection = allowsMultipleSelection;
-    
-    // Show/hide done button
-    if (allowsMultipleSelection) {
-        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)];
-        [self.navigationItem setRightBarButtonItem:doneButton animated:NO];
-    } else {
-        [self.navigationItem setRightBarButtonItem:nil animated:NO];
-    }
-}
-
-- (BOOL)allowsMultipleSelection
-{
-    return self.collectionView.allowsMultipleSelection;
-}
-
-
-#pragma mark - Actions
-
-- (void)done:(id)sender
-{
-    // Delegate
-    if (self.delegate && [self.delegate respondsToSelector:@selector(assetsCollectionViewControllerDidFinishSelection:)]) {
-        [self.delegate assetsCollectionViewControllerDidFinishSelection:self];
-    }
-}
-
-
-#pragma mark - Managing Selection
-
-- (void)selectAssetHavingURL:(NSURL *)URL
-{
-    for (NSInteger i = 0; i < self.assets.count; i++) {
-        ALAsset *asset = self.assets[i];
-        NSURL *assetURL = [asset valueForProperty:ALAssetPropertyAssetURL];
-        
-        if ([assetURL isEqual:URL]) {
-            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
-            [self.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
-            
-            return;
-        }
-    }
-}
-
-
-#pragma mark - Validating Selections
-
-- (BOOL)validateNumberOfSelections:(NSUInteger)numberOfSelections
-{
-    NSUInteger minimumNumberOfSelection = MAX(1, self.minimumNumberOfSelection);
-    BOOL qualifiesMinimumNumberOfSelection = (numberOfSelections >= minimumNumberOfSelection);
-    
-    BOOL qualifiesMaximumNumberOfSelection = YES;
-    if (minimumNumberOfSelection <= self.maximumNumberOfSelection) {
-        qualifiesMaximumNumberOfSelection = (numberOfSelections <= self.maximumNumberOfSelection);
-    }
-    
-    return (qualifiesMinimumNumberOfSelection && qualifiesMaximumNumberOfSelection);
-}
-
-- (BOOL)validateMaximumNumberOfSelections:(NSUInteger)numberOfSelections
-{
-    NSUInteger minimumNumberOfSelection = MAX(1, self.minimumNumberOfSelection);
-    
-    if (minimumNumberOfSelection <= self.maximumNumberOfSelection) {
-        if (numberOfSelections > self.maximumNumberOfSelection) {
-            [MBProgressHUD showAutoMessage:[NSString stringWithFormat:@"������������������%lu���������", (unsigned long)self.maximumNumberOfSelection]];
-        }
-        return (numberOfSelections <= self.maximumNumberOfSelection);
-    }
-    
-    return YES;
-}
-
-
-#pragma mark - UICollectionViewDataSource
-
-- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
-{
-    return 1;
-}
-
-- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
-{
-    return self.numberOfAssets;
-}
-
-- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    QBAssetsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AssetsCell" forIndexPath:indexPath];
-    cell.showsOverlayViewWhenSelected = self.allowsMultipleSelection;
-    
-    ALAsset *asset = self.assets[indexPath.row];
-    cell.asset = asset;
-    
-    return cell;
-}
-
-- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
-{
-    return CGSizeMake(collectionView.bounds.size.width, 46.0);
-}
-
-- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
-{
-    if (kind == UICollectionElementKindSectionFooter) {
-        QBAssetsCollectionFooterView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
-                                                                                      withReuseIdentifier:@"FooterView"
-                                                                                             forIndexPath:indexPath];
-        
-        switch (self.filterType) {
-            case QBImagePickerControllerFilterTypeNone:{
-                NSString *format;
-                if (self.numberOfPhotos == 1) {
-                    if (self.numberOfVideos == 1) {
-                        format = @"format_photo_and_video";
-                    } else {
-                        format = @"format_photo_and_videos";
-                    }
-                } else if (self.numberOfVideos == 1) {
-                    format = @"format_photos_and_video";
-                } else {
-                    format = @"format_photos_and_videos";
-                }
-                footerView.textLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(format,
-                                                                                                  @"QBImagePickerController",
-                                                                                                  nil),
-                                                                                                  self.numberOfPhotos,
-                                                                                                  self.numberOfVideos
-                                                                                                  ];
-                break;
-            }
-                
-            case QBImagePickerControllerFilterTypePhotos:{
-                NSString *format = (self.numberOfPhotos == 1) ? @"format_photo" : @"format_photos";
-                footerView.textLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(format,
-                                                                                                  @"QBImagePickerController",
-                                                                                                  nil),
-                                                                                                  self.numberOfPhotos
-                                                                                                  ];
-                break;
-            }
-                
-            case QBImagePickerControllerFilterTypeVideos:{
-                NSString *format = (self.numberOfVideos == 1) ? @"format_video" : @"format_videos";
-                footerView.textLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(format,
-                                                                                                  @"QBImagePickerController",
-                                                                                                  nil),
-                                                                                                  self.numberOfVideos
-                                                                                                  ];
-                break;
-            }
-        }
-        
-        return footerView;
-    }
-    
-    return nil;
-}
-
-
-#pragma mark - UICollectionViewDelegateFlowLayout
-
-- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    return CGSizeMake(77.5, 77.5);
-}
-
-- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
-{
-    return UIEdgeInsetsMake(2, 2, 2, 2);
-}
-
-- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    return [self validateMaximumNumberOfSelections:(self.imagePickerController.selectedAssetURLs.count + 1)];
-}
-
-- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    ALAsset *asset = self.assets[indexPath.row];
-    
-    // Validation
-    if (self.allowsMultipleSelection) {
-        self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:(self.imagePickerController.selectedAssetURLs.count + 1)];
-    }
-    
-    // Delegate
-    if (self.delegate && [self.delegate respondsToSelector:@selector(assetsCollectionViewController:didSelectAsset:)]) {
-        [self.delegate assetsCollectionViewController:self didSelectAsset:asset];
-    }
-}
-
-- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    ALAsset *asset = self.assets[indexPath.row];
-    
-    // Validation
-    if (self.allowsMultipleSelection) {
-        self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:(self.imagePickerController.selectedAssetURLs.count - 1)];
-    }
-    
-    // Delegate
-    if (self.delegate && [self.delegate respondsToSelector:@selector(assetsCollectionViewController:didDeselectAsset:)]) {
-        [self.delegate assetsCollectionViewController:self didDeselectAsset:asset];
-    }
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.h b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.h
deleted file mode 100755
index f75811e..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-//  QBAssetsCollectionViewLayout.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface QBAssetsCollectionViewLayout : UICollectionViewFlowLayout
-
-+ (instancetype)layout;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.m b/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.m
deleted file mode 100755
index 4d6f452..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBAssetsCollectionViewLayout.m
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  QBAssetsCollectionViewLayout.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBAssetsCollectionViewLayout.h"
-
-@implementation QBAssetsCollectionViewLayout
-
-+ (instancetype)layout
-{
-    return [[self alloc] init];
-}
-
-- (instancetype)init
-{
-    self = [super init];
-    
-    if (self) {
-        self.minimumLineSpacing = 2.0;
-        self.minimumInteritemSpacing = 2.0;
-    }
-    
-    return self;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.h b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.h
deleted file mode 100755
index 006bf6f..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-//  QBImagePickerController.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/30.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-
-typedef NS_ENUM(NSUInteger, QBImagePickerControllerFilterType) {
-    QBImagePickerControllerFilterTypeNone,
-    QBImagePickerControllerFilterTypePhotos,
-    QBImagePickerControllerFilterTypeVideos
-};
-
-UIKIT_EXTERN ALAssetsFilter * ALAssetsFilterFromQBImagePickerControllerFilterType(QBImagePickerControllerFilterType type);
-
-@class QBImagePickerController;
-
-@protocol QBImagePickerControllerDelegate <NSObject>
-
-@optional
-- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didSelectAsset:(ALAsset *)asset;
-- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didSelectAssets:(NSArray *)assets;
-- (void)qb_imagePickerControllerDidCancel:(QBImagePickerController *)imagePickerController;
-
-@end
-
-@interface QBImagePickerController : UITableViewController
-
-@property (nonatomic, strong, readonly) ALAssetsLibrary *assetsLibrary;
-@property (nonatomic, copy, readonly) NSArray *assetsGroups;
-@property (nonatomic, strong, readonly) NSMutableOrderedSet *selectedAssetURLs;
-
-@property (nonatomic, weak) id<QBImagePickerControllerDelegate> delegate;
-@property (nonatomic, copy) NSArray *groupTypes;
-@property (nonatomic, assign) QBImagePickerControllerFilterType filterType;
-@property (nonatomic, assign) BOOL showsCancelButton;
-@property (nonatomic, assign) BOOL allowsMultipleSelection;
-@property (nonatomic, assign) NSUInteger minimumNumberOfSelection;
-@property (nonatomic, assign) NSUInteger maximumNumberOfSelection;
-
-+ (BOOL)isAccessible;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.m b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.m
deleted file mode 100755
index 11ec6eb..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.m
+++ /dev/null
@@ -1,405 +0,0 @@
-//
-//  QBImagePickerController.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/30.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBImagePickerController.h"
-#import <AssetsLibrary/AssetsLibrary.h>
-
-// Views
-#import "QBImagePickerGroupCell.h"
-#import "QBAssetsCollectionViewLayout.h"
-
-// ViewControllers
-#import "QBAssetsCollectionViewController.h"
-
-ALAssetsFilter * ALAssetsFilterFromQBImagePickerControllerFilterType(QBImagePickerControllerFilterType type) {
-    switch (type) {
-        case QBImagePickerControllerFilterTypeNone:
-            return [ALAssetsFilter allAssets];
-            break;
-            
-        case QBImagePickerControllerFilterTypePhotos:
-            return [ALAssetsFilter allPhotos];
-            break;
-            
-        case QBImagePickerControllerFilterTypeVideos:
-            return [ALAssetsFilter allVideos];
-            break;
-    }
-}
-
-@interface QBImagePickerController () <QBAssetsCollectionViewControllerDelegate>
-
-@property (nonatomic, strong, readwrite) ALAssetsLibrary *assetsLibrary;
-@property (nonatomic, copy, readwrite) NSArray *assetsGroups;
-@property (nonatomic, strong, readwrite) NSMutableOrderedSet *selectedAssetURLs;
-@property (nonatomic, assign) BOOL firstShow;
-
-@end
-
-@implementation QBImagePickerController
-
-+ (BOOL)isAccessible
-{
-    return ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary] &&
-            [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]);
-}
-
-- (instancetype)initWithStyle:(UITableViewStyle)style
-{
-    self = [super initWithStyle:UITableViewStylePlain];
-    
-    if (self) {
-        [self setUpProperties];
-    }
-    
-    return self;
-}
-
-- (void)awakeFromNib
-{
-    [super awakeFromNib];
-    
-    [self setUpProperties];
-}
-
-- (void)setUpProperties
-{
-    // Property settings
-    self.selectedAssetURLs = [NSMutableOrderedSet orderedSet];
-    
-    self.groupTypes = @[
-                        @(ALAssetsGroupSavedPhotos),
-                        @(ALAssetsGroupPhotoStream),
-                        @(ALAssetsGroupAlbum)
-                        ];
-    self.filterType = QBImagePickerControllerFilterTypeNone;
-    self.showsCancelButton = YES;
-    
-    // View settings
-    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
-    
-    // Create assets library instance
-    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
-    self.assetsLibrary = assetsLibrary;
-    
-    // Register cell classes
-    [self.tableView registerClass:[QBImagePickerGroupCell class] forCellReuseIdentifier:@"GroupCell"];
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    
-    // View controller settings
-    self.title = NSLocalizedStringFromTable(@"title", @"QBImagePickerController", nil);
-    self.firstShow = YES;
-}
-
-- (void)viewWillAppear:(BOOL)animated
-{
-    [super viewWillAppear:animated];
-    
-    // Load assets groups
-    [self loadAssetsGroupsWithTypes:self.groupTypes
-                         completion:^(NSArray *assetsGroups) {
-                             self.assetsGroups = assetsGroups;
-                             [self.tableView reloadData];
-                             if (self.firstShow) {
-                                 self.firstShow = NO;
-//                                 [self pushToCollectionVCWithIndex:0];
-                             }
-                         }];
-    
-    // Validation
-    self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:self.selectedAssetURLs.count];
-}
-
-
-#pragma mark - Accessors
-
-- (void)setShowsCancelButton:(BOOL)showsCancelButton
-{
-    _showsCancelButton = showsCancelButton;
-    
-    // Show/hide cancel button
-    if (showsCancelButton) {
-        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel:)];
-        [self.navigationItem setLeftBarButtonItem:cancelButton animated:NO];
-    } else {
-        [self.navigationItem setLeftBarButtonItem:nil animated:NO];
-    }
-}
-
-- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection
-{
-    _allowsMultipleSelection = allowsMultipleSelection;
-    
-    // Show/hide done button
-    if (allowsMultipleSelection) {
-        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)];
-        [self.navigationItem setRightBarButtonItem:doneButton animated:NO];
-    } else {
-        [self.navigationItem setRightBarButtonItem:nil animated:NO];
-    }
-}
-
-
-#pragma mark - Actions
-
-- (void)done:(id)sender
-{
-    [self passSelectedAssetsToDelegate];
-}
-
-- (void)cancel:(id)sender
-{
-    // Delegate
-    if (self.delegate && [self.delegate respondsToSelector:@selector(qb_imagePickerControllerDidCancel:)]) {
-		[self.delegate qb_imagePickerControllerDidCancel:self];
-    }
-}
-
-
-#pragma mark - Validating Selections
-
-- (BOOL)validateNumberOfSelections:(NSUInteger)numberOfSelections
-{
-    // Check the number of selected assets
-    NSUInteger minimumNumberOfSelection = MAX(1, self.minimumNumberOfSelection);
-    BOOL qualifiesMinimumNumberOfSelection = (numberOfSelections >= minimumNumberOfSelection);
-    
-    BOOL qualifiesMaximumNumberOfSelection = YES;
-    if (minimumNumberOfSelection <= self.maximumNumberOfSelection) {
-        qualifiesMaximumNumberOfSelection = (numberOfSelections <= self.maximumNumberOfSelection);
-    }
-    
-    return (qualifiesMinimumNumberOfSelection && qualifiesMaximumNumberOfSelection);
-}
-
-
-#pragma mark - Managing Assets
-
-- (void)loadAssetsGroupsWithTypes:(NSArray *)types completion:(void (^)(NSArray *assetsGroups))completion
-{
-    __block NSMutableArray *assetsGroups = [NSMutableArray array];
-    __block NSUInteger numberOfFinishedTypes = 0;
-    
-    for (NSNumber *type in types) {
-        __weak typeof(self) weakSelf = self;
-        
-        [self.assetsLibrary enumerateGroupsWithTypes:[type unsignedIntegerValue]
-                                          usingBlock:^(ALAssetsGroup *assetsGroup, BOOL *stop) {
-                                              if (assetsGroup) {
-                                                  // Filter the assets group
-                                                  [assetsGroup setAssetsFilter:ALAssetsFilterFromQBImagePickerControllerFilterType(weakSelf.filterType)];
-                                                  
-                                                  if (assetsGroup.numberOfAssets > 0) {
-                                                      // Add assets group
-                                                      [assetsGroups addObject:assetsGroup];
-                                                  }
-                                              } else {
-                                                  numberOfFinishedTypes++;
-                                              }
-                                              
-                                              // Check if the loading finished
-                                              if (numberOfFinishedTypes == types.count) {
-                                                  // Sort assets groups
-                                                  NSArray *sortedAssetsGroups = [self sortAssetsGroups:(NSArray *)assetsGroups typesOrder:types];
-                                                  
-                                                  // Call completion block
-                                                  if (completion) {
-                                                      completion(sortedAssetsGroups);
-                                                  }
-                                              }
-                                          } failureBlock:^(NSError *error) {
-                                              NSLog(@"Error: %@", [error localizedDescription]);
-                                          }];
-    }
-}
-
-- (NSArray *)sortAssetsGroups:(NSArray *)assetsGroups typesOrder:(NSArray *)typesOrder
-{
-    NSMutableArray *sortedAssetsGroups = [NSMutableArray array];
-    
-    for (ALAssetsGroup *assetsGroup in assetsGroups) {
-        if (sortedAssetsGroups.count == 0) {
-            [sortedAssetsGroups addObject:assetsGroup];
-            continue;
-        }
-        
-        ALAssetsGroupType assetsGroupType = [[assetsGroup valueForProperty:ALAssetsGroupPropertyType] unsignedIntegerValue];
-        NSUInteger indexOfAssetsGroupType = [typesOrder indexOfObject:@(assetsGroupType)];
-        
-        for (NSInteger i = 0; i <= sortedAssetsGroups.count; i++) {
-            if (i == sortedAssetsGroups.count) {
-                [sortedAssetsGroups addObject:assetsGroup];
-                break;
-            }
-            
-            ALAssetsGroup *sortedAssetsGroup = sortedAssetsGroups[i];
-            ALAssetsGroupType sortedAssetsGroupType = [[sortedAssetsGroup valueForProperty:ALAssetsGroupPropertyType] unsignedIntegerValue];
-            NSUInteger indexOfSortedAssetsGroupType = [typesOrder indexOfObject:@(sortedAssetsGroupType)];
-            
-            if (indexOfAssetsGroupType < indexOfSortedAssetsGroupType) {
-                [sortedAssetsGroups insertObject:assetsGroup atIndex:i];
-                break;
-            }
-        }
-    }
-    
-    return [sortedAssetsGroups copy];
-}
-
-- (void)passSelectedAssetsToDelegate
-{
-    // Load assets from URLs
-    __block NSMutableArray *assets = [NSMutableArray array];
-    __block NSUInteger tryCount = 0;
-    
-    for (NSURL *selectedAssetURL in self.selectedAssetURLs) {
-        __weak typeof(self) weakSelf = self;
-        
-        // Success block
-        void (^selectAsset)(ALAsset *) = ^(ALAsset *asset) {
-            if (asset) {
-                [assets addObject:asset];
-            }
-            // Check if the loading finished
-            if (tryCount == weakSelf.selectedAssetURLs.count) {
-                //NSLog(@"���������������������������%lu", (long)(tryCount - assets.count));
-                // Delegate
-                if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(qb_imagePickerController:didSelectAssets:)]) {
-                    [weakSelf.delegate qb_imagePickerController:weakSelf didSelectAssets:[assets copy]];
-                }
-            }
-        };
-        
-        [self.assetsLibrary assetForURL:selectedAssetURL resultBlock:^(ALAsset *asset) {
-            if (asset) {
-                tryCount++;
-                selectAsset(asset);
-            }else{
-                // Search in the Photo Stream Album
-                [weakSelf.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupPhotoStream usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
-                    [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopG) {
-                        if([result.defaultRepresentation.url isEqual:selectedAssetURL]) {
-                            *stopG = YES;
-                            *stop = YES;
-                            tryCount++;
-                            selectAsset(result);
-                        }else if (index == 0){
-                            NSLog(@"���������");
-                            tryCount++;//���������������������
-                            selectAsset(nil);
-                        }
-                    }];
-                } failureBlock:^(NSError *error) {
-                    NSLog(@"Error: %@", [error localizedDescription]);
-                }];
-            }
-        } failureBlock:^(NSError *error) {
-            NSLog(@"Error: %@", [error localizedDescription]);
-        }];
-    }
-}
-
-
-#pragma mark - UITableViewDataSource
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
-    return 1;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-{
-    return self.assetsGroups.count;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    QBImagePickerGroupCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GroupCell" forIndexPath:indexPath];
-    
-    ALAssetsGroup *assetsGroup = self.assetsGroups[indexPath.row];
-    cell.assetsGroup = assetsGroup;
-    
-    return cell;
-}
-
-
-#pragma mark - UITableViewDelegate
-
-- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    return 86.0;
-}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    [self pushToCollectionVCWithIndex:indexPath.row];
-}
-
-- (void)pushToCollectionVCWithIndex:(NSInteger)index{
-    if (index >= 0 && index < self.assetsGroups.count) {
-        QBAssetsCollectionViewController *assetsCollectionViewController = [[QBAssetsCollectionViewController alloc] initWithCollectionViewLayout:[QBAssetsCollectionViewLayout layout]];
-        assetsCollectionViewController.imagePickerController = self;
-        assetsCollectionViewController.filterType = self.filterType;
-        assetsCollectionViewController.allowsMultipleSelection = self.allowsMultipleSelection;
-        assetsCollectionViewController.minimumNumberOfSelection = self.minimumNumberOfSelection;
-        assetsCollectionViewController.maximumNumberOfSelection = self.maximumNumberOfSelection;
-        
-        ALAssetsGroup *assetsGroup = self.assetsGroups[index];
-        assetsCollectionViewController.delegate = self;
-        assetsCollectionViewController.assetsGroup = assetsGroup;
-        
-        for (NSURL *assetURL in self.selectedAssetURLs) {
-            [assetsCollectionViewController selectAssetHavingURL:assetURL];
-        }
-        
-        [self.navigationController pushViewController:assetsCollectionViewController animated:YES];
-    }
-}
-
-
-#pragma mark - QBAssetsCollectionViewControllerDelegate
-
-- (void)assetsCollectionViewController:(QBAssetsCollectionViewController *)assetsCollectionViewController didSelectAsset:(ALAsset *)asset
-{
-    if (self.allowsMultipleSelection) {
-        // Add asset URL
-        NSURL *assetURL = [asset valueForProperty:ALAssetPropertyAssetURL];
-        [self.selectedAssetURLs addObject:assetURL];
-        
-        // Validation
-        self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:self.selectedAssetURLs.count];
-    } else {
-        // Delegate
-        if (self.delegate && [self.delegate respondsToSelector:@selector(qb_imagePickerController:didSelectAsset:)]) {
-			[self.delegate qb_imagePickerController:self didSelectAsset:asset];
-        }
-    }
-}
-
-- (void)assetsCollectionViewController:(QBAssetsCollectionViewController *)assetsCollectionViewController didDeselectAsset:(ALAsset *)asset
-{
-    if (self.allowsMultipleSelection) {
-        // Remove asset URL
-        NSURL *assetURL = [asset valueForProperty:ALAssetPropertyAssetURL];
-        [self.selectedAssetURLs removeObject:assetURL];
-        
-        // Validation
-        self.navigationItem.rightBarButtonItem.enabled = [self validateNumberOfSelections:self.selectedAssetURLs.count];
-    }
-}
-
-- (void)assetsCollectionViewControllerDidFinishSelection:(QBAssetsCollectionViewController *)assetsCollectionViewController
-{
-    [self passSelectedAssetsToDelegate];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.strings b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.strings
deleted file mode 100755
index dfc7cce..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerController.strings
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 
-  QBImagePickerController.strings
-  QBImagePickerControllerDemo
-
-  Created by Tanaka Katsuma on 2014/01/01.
-  Copyright (c) 2014��� Katsuma Tanaka. All rights reserved.
-*/
-
-"title" = "������";
-
-"format_photo" = "���%ld���������";
-"format_photos" = "���%ld���������";
-"format_video" = "%���ld���������";
-"format_videos" = "���%ld���������";
-"format_photo_and_video" = "%���ld���������, %ld���������";
-"format_photos_and_video" = "%���ld���������, %ld���������";
-"format_photo_and_videos" = "%���ld���������, %ld���������";
-"format_photos_and_videos" = "%���ld���������, %ld���������";
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.h b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.h
deleted file mode 100755
index a6480ae..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-//  QBImagePickerGroupCell.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/30.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-
-@interface QBImagePickerGroupCell : UITableViewCell
-
-@property (nonatomic, strong) ALAssetsGroup *assetsGroup;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.m b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.m
deleted file mode 100755
index c5bdac5..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerGroupCell.m
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-//  QBImagePickerGroupCell.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/30.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBImagePickerGroupCell.h"
-
-// Views
-#import "QBImagePickerThumbnailView.h"
-
-@interface QBImagePickerGroupCell ()
-
-@property (nonatomic, strong) QBImagePickerThumbnailView *thumbnailView;
-@property (nonatomic, strong) UILabel *nameLabel;
-@property (nonatomic, strong) UILabel *countLabel;
-
-@end
-
-@implementation QBImagePickerGroupCell
-
-- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
-{
-    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
-    
-    if (self) {
-        // Cell settings
-        self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
-        
-        // Create thumbnail view
-        QBImagePickerThumbnailView *thumbnailView = [[QBImagePickerThumbnailView alloc] initWithFrame:CGRectMake(8, 4, 70, 74)];
-        thumbnailView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
-        
-        [self.contentView addSubview:thumbnailView];
-        self.thumbnailView = thumbnailView;
-        
-        // Create name label
-        UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(8 + 70 + 18, 22, 180, 21)];
-        nameLabel.font = [UIFont systemFontOfSize:17];
-        nameLabel.textColor = [UIColor blackColor];
-        nameLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
-        
-        [self.contentView addSubview:nameLabel];
-        self.nameLabel = nameLabel;
-        
-        // Create count label
-        UILabel *countLabel = [[UILabel alloc] initWithFrame:CGRectMake(8 + 70 + 18, 46, 180, 15)];
-        countLabel.font = [UIFont systemFontOfSize:12];
-        countLabel.textColor = [UIColor blackColor];
-        countLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
-        
-        [self.contentView addSubview:countLabel];
-        self.countLabel = countLabel;
-    }
-    
-    return self;
-}
-
-
-#pragma mark - Accessors
-
-- (void)setAssetsGroup:(ALAssetsGroup *)assetsGroup
-{
-    _assetsGroup = assetsGroup;
-    
-    // Update thumbnail view
-    self.thumbnailView.assetsGroup = self.assetsGroup;
-    
-    // Update label
-    self.nameLabel.text = [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName];
-    self.countLabel.text = [NSString stringWithFormat:@"%ld", (long)self.assetsGroup.numberOfAssets];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.h b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.h
deleted file mode 100755
index 2b5eeaa..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-//  QBImagePickerThumbnailView.h
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-
-@interface QBImagePickerThumbnailView : UIView
-
-@property (nonatomic, strong) ALAssetsGroup *assetsGroup;
-
-@end
diff --git a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.m b/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.m
deleted file mode 100755
index ea05a6c..0000000
--- a/camerademo/camerademo/demo/QBImagePickerController/QBImagePickerThumbnailView.m
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-//  QBImagePickerThumbnailView.m
-//  QBImagePickerController
-//
-//  Created by Tanaka Katsuma on 2013/12/31.
-//  Copyright (c) 2013��� Katsuma Tanaka. All rights reserved.
-//
-
-#import "QBImagePickerThumbnailView.h"
-
-@interface QBImagePickerThumbnailView ()
-
-@property (nonatomic, copy) NSArray *thumbnailImages;
-@property (nonatomic, strong) UIImage *blankImage;
-
-@end
-
-@implementation QBImagePickerThumbnailView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    self = [super initWithFrame:frame];
-    
-    if (self) {
-        self.backgroundColor = [UIColor clearColor];
-    }
-    
-    return self;
-}
-
-- (CGSize)sizeThatFits:(CGSize)size
-{
-    return CGSizeMake(70.0, 74.0);
-}
-
-- (void)drawRect:(CGRect)rect
-{
-    [super drawRect:rect];
-    
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
-    
-    if (self.thumbnailImages.count == 3) {
-        UIImage *thumbnailImage = [self.thumbnailImages firstObject];
-        
-        CGRect thumbnailImageRect = CGRectMake(4.0, 0, 62.0, 62.0);
-        CGContextFillRect(context, thumbnailImageRect);
-        [thumbnailImage drawInRect:CGRectInset(thumbnailImageRect, 0.5, 0.5)];
-    }
-    if (self.thumbnailImages.count >= 2) {
-        UIImage *thumbnailImage = self.thumbnailImages[1];
-        
-        CGRect thumbnailImageRect = CGRectMake(2.0, 2.0, 66.0, 66.0);
-        CGContextFillRect(context, thumbnailImageRect);
-        [thumbnailImage drawInRect:CGRectInset(thumbnailImageRect, 0.5, 0.5)];
-    }
-    if (self.thumbnailImages.count >= 1) {
-        UIImage *thumbnailImage = [self.thumbnailImages lastObject];
-        
-        CGRect thumbnailImageRect = CGRectMake(0, 4.0, 70.0, 70.0);
-        CGContextFillRect(context, thumbnailImageRect);
-        [thumbnailImage drawInRect:CGRectInset(thumbnailImageRect, 0.5, 0.5)];
-    }
-}
-
-
-#pragma mark - Accessors
-
-- (void)setAssetsGroup:(ALAssetsGroup *)assetsGroup
-{
-    _assetsGroup = assetsGroup;
-    
-    // Extract three thumbnail images
-    NSInteger thumbnailImagesCount = MIN(3, assetsGroup.numberOfAssets);
-    NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(assetsGroup.numberOfAssets-thumbnailImagesCount, thumbnailImagesCount)];
-    NSMutableArray *thumbnailImages = [NSMutableArray array];
-    [assetsGroup enumerateAssetsAtIndexes:indexes
-                                  options:0
-                               usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
-                                   if (result) {
-                                       CGImageRef thumbnailImageRef = [result thumbnail];
-                                       
-                                       if (thumbnailImageRef) {
-                                           [thumbnailImages addObject:[UIImage imageWithCGImage:thumbnailImageRef]];
-                                       } else {
-                                           [thumbnailImages addObject:[self blankImage]];
-                                       }
-                                   }
-                               }];
-    self.thumbnailImages = [thumbnailImages copy];
-    
-    [self setNeedsDisplay];
-}
-
-- (UIImage *)blankImage
-{
-    if (_blankImage == nil) {
-        CGSize size = CGSizeMake(100.0, 100.0);
-        UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
-        
-        [[UIColor colorWithWhite:(240.0 / 255.0) alpha:1.0] setFill];
-        UIRectFill(CGRectMake(0, 0, size.width, size.height));
-        
-        _blankImage = UIGraphicsGetImageFromCurrentImageContext();
-        
-        UIGraphicsEndImageContext();
-    }
-    
-    return _blankImage;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Alpha.h b/camerademo/camerademo/demo/UIImage/UIImage+Alpha.h
deleted file mode 100755
index ba09684..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Alpha.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// UIImage+Alpha.h
-// Created by Trevor Harmon on 9/20/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-// Helper methods for adding an alpha layer to an image
-#import <UIKit/UIKit.h>
-
-@interface UIImage (Alpha)
-/**
- *  @brief  ���������alpha������
- *
- *  @return ���������alpha������
- */
-- (BOOL)hasAlpha;
-/**
- *  @brief  ������������alpha������ ������alpha������
- *
- *  @return ������������alpha������ ������alpha������
- */
-- (UIImage *)imageWithAlpha;
-/**
- *  @brief  ������������������
- *
- *  @param borderSize ������������
- *
- *  @return ������������������������������
- */
-- (UIImage *)transparentBorderImage:(NSUInteger)borderSize;
-
-
-//http://stackoverflow.com/questions/6521987/crop-uiimage-to-alpha?answertab=oldest#tab-top
-/**
- *  @brief  ������������������������������������
- *
- *  @return ������������������
- */
-- (UIImage *)trimmedBetterSize;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Alpha.m b/camerademo/camerademo/demo/UIImage/UIImage+Alpha.m
deleted file mode 100755
index fba6259..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Alpha.m
+++ /dev/null
@@ -1,234 +0,0 @@
-// UIImage+Alpha.m
-// Created by Trevor Harmon on 9/20/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-#import "UIImage+Alpha.h"
-
-// Private helper methods
-@interface UIImage (AlphaPrivateMethods)
-- (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size;
-@end
-
-@implementation UIImage (Alpha)
-/**
- *  @brief  ���������alpha������
- *
- *  @return ���������alpha������
- */
-- (BOOL)hasAlpha {
-    CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
-    return (alpha == kCGImageAlphaFirst ||
-            alpha == kCGImageAlphaLast ||
-            alpha == kCGImageAlphaPremultipliedFirst ||
-            alpha == kCGImageAlphaPremultipliedLast);
-}
-/**
- *  @brief  ������������alpha������ ������alpha������
- *
- *  @return ������������alpha������ ������alpha������
- */
-- (UIImage *)imageWithAlpha {
-    if ([self hasAlpha]) {
-        return self;
-    }
-    
-    CGImageRef imageRef = self.CGImage;
-    size_t width = CGImageGetWidth(imageRef);
-    size_t height = CGImageGetHeight(imageRef);
-    
-    // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error
-    CGContextRef offscreenContext = CGBitmapContextCreate(NULL,
-                                                          width,
-                                                          height,
-                                                          8,
-                                                          0,
-                                                          CGImageGetColorSpace(imageRef),
-                                                          kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
-    
-    // Draw the image into the context and retrieve the new image, which will now have an alpha layer
-    CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), imageRef);
-    CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(offscreenContext);
-    UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];
-    
-    // Clean up
-    CGContextRelease(offscreenContext);
-    CGImageRelease(imageRefWithAlpha);
-    
-    return imageWithAlpha;
-}
-
-// Returns a copy of the image with a transparent border of the given size added around its edges.
-// If the image has no alpha layer, one will be added to it.
-/**
- *  @brief  ������������������
- *
- *  @param borderSize ������������
- *
- *  @return ������������������������������
- */
-- (UIImage *)transparentBorderImage:(NSUInteger)borderSize {
-    // If the image does not have an alpha layer, add one
-    UIImage *image = [self imageWithAlpha];
-    
-    CGRect newRect = CGRectMake(0, 0, image.size.width + borderSize * 2, image.size.height + borderSize * 2);
-    
-    // Build a context that's the same dimensions as the new size
-    CGContextRef bitmap = CGBitmapContextCreate(NULL,
-                                                newRect.size.width,
-                                                newRect.size.height,
-                                                CGImageGetBitsPerComponent(self.CGImage),
-                                                0,
-                                                CGImageGetColorSpace(self.CGImage),
-                                                CGImageGetBitmapInfo(self.CGImage));
-    
-    // Draw the image in the center of the context, leaving a gap around the edges
-    CGRect imageLocation = CGRectMake(borderSize, borderSize, image.size.width, image.size.height);
-    CGContextDrawImage(bitmap, imageLocation, self.CGImage);
-    CGImageRef borderImageRef = CGBitmapContextCreateImage(bitmap);
-    
-    // Create a mask to make the border transparent, and combine it with the image
-    CGImageRef maskImageRef = [self newBorderMask:borderSize size:newRect.size];
-    CGImageRef transparentBorderImageRef = CGImageCreateWithMask(borderImageRef, maskImageRef);
-    UIImage *transparentBorderImage = [UIImage imageWithCGImage:transparentBorderImageRef];
-    
-    // Clean up
-    CGContextRelease(bitmap);
-    CGImageRelease(borderImageRef);
-    CGImageRelease(maskImageRef);
-    CGImageRelease(transparentBorderImageRef);
-    
-    return transparentBorderImage;
-}
-/**
- *  @brief  ������������������������������������
- *
- *  @return ������������������
- */
-- (UIImage *)trimmedBetterSize {
-    
-    CGImageRef inImage = self.CGImage;
-    CFDataRef m_DataRef;
-    m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
-    
-    UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);
-    
-//    size_t width = CGImageGetWidth(inImage);
-//    size_t height = CGImageGetHeight(inImage);
-    CGFloat width = CGImageGetWidth(inImage);
-    CGFloat height = CGImageGetHeight(inImage);
-    CGPoint top,left,right,bottom;
-    
-    BOOL breakOut = NO;
-    for (int x = 0;breakOut==NO && x < width; x++) {
-        for (int y = 0; y < height; y++) {
-            int loc = x + (y * width);
-            loc *= 4;
-            if (m_PixelBuf[loc + 3] != 0) {
-                left = CGPointMake(x, y);
-                breakOut = YES;
-                break;
-            }
-        }
-    }
-    
-    breakOut = NO;
-    for (int y = 0;breakOut==NO && y < height; y++) {
-        
-        for (int x = 0; x < width; x++) {
-            
-            int loc = x + (y * width);
-            loc *= 4;
-            if (m_PixelBuf[loc + 3] != 0) {
-                top = CGPointMake(x, y);
-                breakOut = YES;
-                break;
-            }
-            
-        }
-    }
-    
-    breakOut = NO;
-    for (int y = height-1;breakOut==NO && y >= 0; y--) {
-        
-        for (int x = width-1; x >= 0; x--) {
-            
-            int loc = x + (y * width);
-            loc *= 4;
-            if (m_PixelBuf[loc + 3] != 0) {
-                bottom = CGPointMake(x, y);
-                breakOut = YES;
-                break;
-            }
-            
-        }
-    }
-    
-    breakOut = NO;
-    for (int x = width-1;breakOut==NO && x >= 0; x--) {
-        
-        for (int y = height-1; y >= 0; y--) {
-            
-            int loc = x + (y * width);
-            loc *= 4;
-            if (m_PixelBuf[loc + 3] != 0) {
-                right = CGPointMake(x, y);
-                breakOut = YES;
-                break;
-            }
-            
-        }
-    }
-    
-    
-    CGFloat scale = self.scale;
-    
-    CGRect cropRect = CGRectMake(left.x / scale, top.y/scale, (right.x - left.x)/scale, (bottom.y - top.y) / scale);
-    UIGraphicsBeginImageContextWithOptions( cropRect.size,
-                                           NO,
-                                           scale);
-    [self drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y)
-            blendMode:kCGBlendModeCopy
-                alpha:1.];
-    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    CFRelease(m_DataRef);
-    return croppedImage;
-}
-#pragma mark -
-#pragma mark Private helper methods
-
-// Creates a mask that makes the outer edges transparent and everything else opaque
-// The size must include the entire mask (opaque part + transparent border)
-// The caller is responsible for releasing the returned reference by calling CGImageRelease
-- (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size {
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
-    
-    // Build a context that's the same dimensions as the new size
-    CGContextRef maskContext = CGBitmapContextCreate(NULL,
-                                                     size.width,
-                                                     size.height,
-                                                     8, // 8-bit grayscale
-                                                     0,
-                                                     colorSpace,
-                                                     kCGBitmapByteOrderDefault | kCGImageAlphaNone);
-    
-    // Start with a mask that's entirely transparent
-    CGContextSetFillColorWithColor(maskContext, [UIColor blackColor].CGColor);
-    CGContextFillRect(maskContext, CGRectMake(0, 0, size.width, size.height));
-    
-    // Make the inner part (within the border) opaque
-    CGContextSetFillColorWithColor(maskContext, [UIColor whiteColor].CGColor);
-    CGContextFillRect(maskContext, CGRectMake(borderSize, borderSize, size.width - borderSize * 2, size.height - borderSize * 2));
-    
-    // Get an image of the context
-    CGImageRef maskImageRef = CGBitmapContextCreateImage(maskContext);
-    
-    // Clean up
-    CGContextRelease(maskContext);
-    CGColorSpaceRelease(colorSpace);
-    
-    return maskImageRef;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.h b/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.h
deleted file mode 100755
index 95fa0d6..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-//  UIImage+BetterFace.h
-//  bf
-//
-//  Created by liuyan on 13-11-25.
-//  Copyright (c) 2013��� Croath. All rights reserved.
-//
-// https://github.com/croath/UIImageView-BetterFace
-//  a UIImageView category to let the picture-cutting with faces showing better
-
-#import <UIKit/UIKit.h>
-
-typedef NS_ENUM(NSUInteger, BFAccuracy) {
-    kBFAccuracyLow = 0,
-    kBFAccuracyHigh,
-};
-
-@interface UIImage (BetterFace)
-
-- (UIImage *)betterFaceImageForSize:(CGSize)size
-                           accuracy:(BFAccuracy)accurary;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.m b/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.m
deleted file mode 100755
index f776f71..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+BetterFace.m
+++ /dev/null
@@ -1,111 +0,0 @@
-//
-//  UIImage+BetterFace.m
-//  bf
-//
-//  Created by liuyan on 13-11-25.
-//  Copyright (c) 2013��� Croath. All rights reserved.
-//
-
-#import "UIImage+BetterFace.h"
-
-#define GOLDEN_RATIO (0.618)
-
-#ifdef BF_DEBUG
-#define BFLog(format...) NSLog(format)
-#else
-#define BFLog(format...)
-#endif
-
-@implementation UIImage (BetterFace)
-
-- (UIImage *)betterFaceImageForSize:(CGSize)size
-                           accuracy:(BFAccuracy)accurary;
-{
-    NSArray *features = [UIImage _faceFeaturesInImage:self accuracy:accurary];
-    
-    if ([features count]==0) {
-        BFLog(@"no faces");
-        return nil;
-    } else {
-        BFLog(@"succeed %lu faces", (unsigned long)[features count]);
-        return [self _subImageForFaceFeatures:features
-                                         size:size];
-    }
-}
-
-- (UIImage *)_subImageForFaceFeatures:(NSArray *)faceFeatures size:(CGSize)size
-{
-    CGRect fixedRect = CGRectMake(MAXFLOAT, MAXFLOAT, 0, 0);
-    CGFloat rightBorder = 0, bottomBorder = 0;
-    for (CIFaceFeature *faceFeature in faceFeatures){
-        CGRect oneRect = faceFeature.bounds;
-        oneRect.origin.y = size.height - oneRect.origin.y - oneRect.size.height;
-        
-        fixedRect.origin.x = MIN(oneRect.origin.x, fixedRect.origin.x);
-        fixedRect.origin.y = MIN(oneRect.origin.y, fixedRect.origin.y);
-        
-        rightBorder = MAX(oneRect.origin.x + oneRect.size.width, rightBorder);
-        bottomBorder = MAX(oneRect.origin.y + oneRect.size.height, bottomBorder);
-    }
-    
-    fixedRect.size.width = rightBorder - fixedRect.origin.x;
-    fixedRect.size.height = bottomBorder - fixedRect.origin.y;
-    
-    CGPoint fixedCenter = CGPointMake(fixedRect.origin.x + fixedRect.size.width / 2.0,
-                                      fixedRect.origin.y + fixedRect.size.height / 2.0);
-    CGPoint offset = CGPointZero;
-    CGSize finalSize = size;
-    if (size.width / size.height > self.size.width / self.size.height) {
-        //move horizonal
-        finalSize.height = self.size.height;
-        finalSize.width = size.width/size.height * finalSize.height;
-        fixedCenter.x = finalSize.width / size.width * fixedCenter.x;
-        fixedCenter.y = finalSize.width / size.width * fixedCenter.y;
-        
-        offset.x = fixedCenter.x - self.size.width * 0.5;
-        if (offset.x < 0) {
-            offset.x = 0;
-        } else if (offset.x + self.size.width > finalSize.width) {
-            offset.x = finalSize.width - self.size.width;
-        }
-        offset.x = - offset.x;
-    } else {
-        //move vertical
-        finalSize.width = self.size.width;
-        finalSize.height = size.height/size.width * finalSize.width;
-        fixedCenter.x = finalSize.width / size.width * fixedCenter.x;
-        fixedCenter.y = finalSize.width / size.width * fixedCenter.y;
-        
-        offset.y = fixedCenter.y - self.size.height * (1-GOLDEN_RATIO);
-        if (offset.y < 0) {
-            offset.y = 0;
-        } else if (offset.y + self.size.height > finalSize.height){
-            offset.y = finalSize.height = self.size.height;
-        }
-        offset.y = - offset.y;
-    }
-    
-    CGRect finalRect = CGRectApplyAffineTransform(CGRectMake(offset.x, offset.y, finalSize.width, finalSize.height),
-                                                  CGAffineTransformMakeScale(self.scale, self.scale));
-    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], finalRect);
-    UIImage *subImage = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
-    CGImageRelease(imageRef);
-    
-    return subImage;
-}
-
-#pragma mark - Util
-
-+ (NSArray *)_faceFeaturesInImage:(UIImage *)image accuracy:(BFAccuracy)accurary
-{
-    CIImage *ciImage = [CIImage imageWithCGImage:image.CGImage];
-    NSString *accuraryStr = (accurary == kBFAccuracyLow) ? CIDetectorAccuracyLow : CIDetectorAccuracyHigh;
-    
-    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
-                                              context:nil
-                                              options:@{CIDetectorAccuracy: accuraryStr}];
-    
-    return [detector featuresInImage:ciImage];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Blur.h b/camerademo/camerademo/demo/UIImage/UIImage+Blur.h
deleted file mode 100755
index 4f5f82b..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Blur.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-//  UIImage+Blur.h
-//  IOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/6/5.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-FOUNDATION_EXPORT double ImageEffectsVersionNumber;
-FOUNDATION_EXPORT const unsigned char ImageEffectsVersionString[];
-@interface UIImage (Blur)
-- (UIImage *)lightImage;
-- (UIImage *)extraLightImage;
-- (UIImage *)darkImage;
-- (UIImage *)tintedImageWithColor:(UIColor *)tintColor;
-
-- (UIImage *)blurredImageWithRadius:(CGFloat)blurRadius;
-- (UIImage *)blurredImageWithSize:(CGSize)blurSize;
-- (UIImage *)blurredImageWithSize:(CGSize)blurSize
-                        tintColor:(UIColor *)tintColor
-            saturationDeltaFactor:(CGFloat)saturationDeltaFactor
-                        maskImage:(UIImage *)maskImage;
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Blur.m b/camerademo/camerademo/demo/UIImage/UIImage+Blur.m
deleted file mode 100755
index 70f4461..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Blur.m
+++ /dev/null
@@ -1,281 +0,0 @@
-//
-//  UIImage+Blur.m
-//  IOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/6/5.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+Blur.h"
-@import Accelerate;
-@implementation UIImage (Blur)
-#pragma mark -
-#pragma mark - Effects
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)lightImage
-{
-    UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
-    return [self blurredImageWithSize:CGSizeMake(60, 60) tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
-}
-
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)extraLightImage
-{
-    UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
-    return [self blurredImageWithSize:CGSizeMake(40, 40) tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
-}
-
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)darkImage
-{
-    UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
-    return [self blurredImageWithSize:CGSizeMake(40, 40) tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
-}
-
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)tintedImageWithColor:(UIColor *)tintColor
-{
-    const CGFloat EffectColorAlpha = 0.6;
-    UIColor *effectColor = tintColor;
-    size_t componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
-    if (componentCount == 2) {
-        CGFloat b;
-        if ([tintColor getWhite:&b alpha:NULL]) {
-            effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
-        }
-    }
-    else {
-        CGFloat r, g, b;
-        if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
-            effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
-        }
-    }
-    return [self blurredImageWithSize:CGSizeMake(20, 20) tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
-}
-
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)blurredImageWithRadius:(CGFloat)blurRadius
-{
-    return [self blurredImageWithSize:CGSizeMake(blurRadius, blurRadius)];
-}
-
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)blurredImageWithSize:(CGSize)blurSize
-{
-    return [self blurredImageWithSize:blurSize tintColor:nil saturationDeltaFactor:1.0 maskImage:nil];
-}
-
-#pragma mark -
-#pragma mark - Implementation
-
-//| ----------------------------------------------------------------------------
-- (UIImage *)blurredImageWithSize:(CGSize)blurSize tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
-{
-#define ENABLE_BLUR                     1
-#define ENABLE_SATURATION_ADJUSTMENT    1
-#define ENABLE_TINT                     1
-    
-    // Check pre-conditions.
-    if (self.size.width < 1 || self.size.height < 1)
-    {
-        NSLog(@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
-        return nil;
-    }
-    if (!self.CGImage)
-    {
-        NSLog(@"*** error: inputImage must be backed by a CGImage: %@", self);
-        return nil;
-    }
-    if (maskImage && !maskImage.CGImage)
-    {
-        NSLog(@"*** error: effectMaskImage must be backed by a CGImage: %@", maskImage);
-        return nil;
-    }
-    
-    BOOL hasBlur = blurSize.width > __FLT_EPSILON__ || blurSize.height > __FLT_EPSILON__;
-    BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
-    
-    CGImageRef inputCGImage = self.CGImage;
-    CGFloat inputImageScale = self.scale;
-    CGBitmapInfo inputImageBitmapInfo = CGImageGetBitmapInfo(inputCGImage);
-    CGImageAlphaInfo inputImageAlphaInfo = (inputImageBitmapInfo & kCGBitmapAlphaInfoMask);
-    
-    CGSize outputImageSizeInPoints = self.size;
-    CGRect outputImageRectInPoints = { CGPointZero, outputImageSizeInPoints };
-    
-    // Set up output context.
-    BOOL useOpaqueContext;
-    if (inputImageAlphaInfo == kCGImageAlphaNone || inputImageAlphaInfo == kCGImageAlphaNoneSkipLast || inputImageAlphaInfo == kCGImageAlphaNoneSkipFirst)
-        useOpaqueContext = YES;
-    else
-        useOpaqueContext = NO;
-    UIGraphicsBeginImageContextWithOptions(outputImageRectInPoints.size, useOpaqueContext, inputImageScale);
-    CGContextRef outputContext = UIGraphicsGetCurrentContext();
-    CGContextScaleCTM(outputContext, 1.0, -1.0);
-    CGContextTranslateCTM(outputContext, 0, -outputImageRectInPoints.size.height);
-    
-    if (hasBlur || hasSaturationChange)
-    {
-        vImage_Buffer effectInBuffer;
-        vImage_Buffer scratchBuffer1;
-        
-        vImage_Buffer *inputBuffer;
-        vImage_Buffer *outputBuffer;
-        
-        vImage_CGImageFormat format = {
-            .bitsPerComponent = 8,
-            .bitsPerPixel = 32,
-            .colorSpace = NULL,
-            // (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
-            // requests a BGRA buffer.
-            .bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little,
-            .version = 0,
-            .decode = NULL,
-            .renderingIntent = kCGRenderingIntentDefault
-        };
-        
-        vImage_Error e = vImageBuffer_InitWithCGImage(&effectInBuffer, &format, NULL, self.CGImage, kvImagePrintDiagnosticsToConsole);
-        if (e != kvImageNoError)
-        {
-            NSLog(@"*** error: vImageBuffer_InitWithCGImage returned error code %zi for inputImage: %@", e, self);
-            UIGraphicsEndImageContext();
-            return nil;
-        }
-        
-        vImageBuffer_Init(&scratchBuffer1, effectInBuffer.height, effectInBuffer.width, format.bitsPerPixel, kvImageNoFlags);
-        inputBuffer = &effectInBuffer;
-        outputBuffer = &scratchBuffer1;
-        
-#if ENABLE_BLUR
-        if (hasBlur)
-        {
-            CGFloat radiusX = [self gaussianBlurRadiusWithBlurRadius:blurSize.width * inputImageScale];
-            CGFloat radiusY = [self gaussianBlurRadiusWithBlurRadius:blurSize.height * inputImageScale];
-            
-            NSInteger tempBufferSize = vImageBoxConvolve_ARGB8888(inputBuffer, outputBuffer, NULL, 0, 0, radiusY, radiusX, NULL, kvImageGetTempBufferSize | kvImageEdgeExtend);
-            void *tempBuffer = malloc(tempBufferSize);
-            
-            vImageBoxConvolve_ARGB8888(inputBuffer, outputBuffer, tempBuffer, 0, 0, radiusY, radiusX, NULL, kvImageEdgeExtend);
-            vImageBoxConvolve_ARGB8888(outputBuffer, inputBuffer, tempBuffer, 0, 0, radiusY, radiusX, NULL, kvImageEdgeExtend);
-            vImageBoxConvolve_ARGB8888(inputBuffer, outputBuffer, tempBuffer, 0, 0, radiusY, radiusX, NULL, kvImageEdgeExtend);
-            
-            free(tempBuffer);
-            
-            vImage_Buffer *temp = inputBuffer;
-            inputBuffer = outputBuffer;
-            outputBuffer = temp;
-        }
-#endif
-        
-#if ENABLE_SATURATION_ADJUSTMENT
-        if (hasSaturationChange)
-        {
-            CGFloat s = saturationDeltaFactor;
-            // These values appear in the W3C Filter Effects spec:
-            // https://dvcs.w3.org/hg/FXTF/raw-file/default/filters/index.html#grayscaleEquivalent
-            //
-            CGFloat floatingPointSaturationMatrix[] = {
-                0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
-                0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
-                0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
-                0,                    0,                    0,                    1,
-            };
-            const int32_t divisor = 256;
-            NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
-            int16_t saturationMatrix[matrixSize];
-            for (NSUInteger i = 0; i < matrixSize; ++i) {
-                saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
-            }
-            vImageMatrixMultiply_ARGB8888(inputBuffer, outputBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
-            
-            vImage_Buffer *temp = inputBuffer;
-            inputBuffer = outputBuffer;
-            outputBuffer = temp;
-        }
-#endif
-        
-        CGImageRef effectCGImage;
-        if ( (effectCGImage = vImageCreateCGImageFromBuffer(inputBuffer, &format, &cleanupBuffer, NULL, kvImageNoAllocate, NULL)) == NULL ) {
-            effectCGImage = vImageCreateCGImageFromBuffer(inputBuffer, &format, NULL, NULL, kvImageNoFlags, NULL);
-            free(inputBuffer->data);
-        }
-        if (maskImage) {
-            // Only need to draw the base image if the effect image will be masked.
-            CGContextDrawImage(outputContext, outputImageRectInPoints, inputCGImage);
-        }
-        
-        // draw effect image
-        CGContextSaveGState(outputContext);
-        if (maskImage)
-            CGContextClipToMask(outputContext, outputImageRectInPoints, maskImage.CGImage);
-        CGContextDrawImage(outputContext, outputImageRectInPoints, effectCGImage);
-        CGContextRestoreGState(outputContext);
-        
-        // Cleanup
-        CGImageRelease(effectCGImage);
-        free(outputBuffer->data);
-    }
-    else
-    {
-        // draw base image
-        CGContextDrawImage(outputContext, outputImageRectInPoints, inputCGImage);
-    }
-    
-#if ENABLE_TINT
-    // Add in color tint.
-    if (tintColor)
-    {
-        CGContextSaveGState(outputContext);
-        CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
-        CGContextFillRect(outputContext, outputImageRectInPoints);
-        CGContextRestoreGState(outputContext);
-    }
-#endif
-    
-    // Output image is ready.
-    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    
-    return outputImage;
-#undef ENABLE_BLUR
-#undef ENABLE_SATURATION_ADJUSTMENT
-#undef ENABLE_TINT
-}
-
-
-// A description of how to compute the box kernel width from the Gaussian
-// radius (aka standard deviation) appears in the SVG spec:
-// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
-//
-// For larger values of 's' (s >= 2.0), an approximation can be used: Three
-// successive box-blurs build a piece-wise quadratic convolution kernel, which
-// approximates the Gaussian kernel to within roughly 3%.
-//
-// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
-//
-// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
-//
-- (CGFloat)gaussianBlurRadiusWithBlurRadius:(CGFloat)blurRadius
-{
-    if (blurRadius - 2. < __FLT_EPSILON__) {
-        blurRadius = 2.;
-    }
-    uint32_t radius = floor((blurRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5) / 2);
-    radius |= 1; // force radius to be odd so that the three box-blur methodology works.
-    return radius;
-}
-
-
-//| ----------------------------------------------------------------------------
-//  Helper function to handle deferred cleanup of a buffer.
-//
-void cleanupBuffer(void *userData, void *buf_data)
-{ free(buf_data); }
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Capture.h b/camerademo/camerademo/demo/UIImage/UIImage+Capture.h
deleted file mode 100755
index 36ccac3..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Capture.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-//  UIImage+Capture.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/10.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (Capture)
-/**
- *  @brief  ������������view���������
- *
- *  @param view ������view
- *
- *  @return ������
- */
-+ (UIImage *)captureWithView:(UIView *)view;
-
-///���������������������������������
-+ (UIImage *)getImageWithSize:(CGRect)myImageRect FromImage:(UIImage *)bigImage;
-
-/**
- *  @author Jakey
- *
- *  @brief  ������������view��������������� ������������������������
- *
- *  @param aView    ���������view
- *  @param maxWidth ������������ 0���view������������
- *
- *  @return ������
- */
-+ (UIImage *)screenshotWithView:(UIView *)aView limitWidth:(CGFloat)maxWidth;
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Capture.m b/camerademo/camerademo/demo/UIImage/UIImage+Capture.m
deleted file mode 100755
index e376c89..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Capture.m
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-//  UIImage+Capture.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/10.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+Capture.h"
-#import <QuartzCore/QuartzCore.h>
-@implementation UIImage (Capture)
-/**
- *  @brief  ������������view���������
- *
- *  @param view ������view
- *
- *  @return ������
- */
-+ (UIImage *)captureWithView:(UIView *)view
-{
-    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [UIScreen mainScreen].scale);
-    // IOS7������������������
-    if ([view respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
-        [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
-    } else { // IOS7���������������
-        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
-    }
-    
-    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    return screenshot;
-}
-
-+ (UIImage *)getImageWithSize:(CGRect)myImageRect FromImage:(UIImage *)bigImage
-{
-    //������bigImage
-    //������myImageRect������������������
-    CGImageRef imageRef = bigImage.CGImage;
-    CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, myImageRect);
-    CGSize size;
-    size.width = CGRectGetWidth(myImageRect);
-    size.height = CGRectGetHeight(myImageRect);
-    UIGraphicsBeginImageContext(size);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    CGContextDrawImage(context, myImageRect, subImageRef);
-    UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
-    CGImageRelease(subImageRef);
-    UIGraphicsEndImageContext();
-    return smallImage;
-}
-
-/**
- *  @author Jakey
- *
- *  @brief  ������������view��������������� ������������������������
- *
- *  @param aView    ���������view
- *  @param maxWidth ������������ 0���view������������
- *
- *  @return ������
- */
-+ (UIImage *)screenshotWithView:(UIView *)aView limitWidth:(CGFloat)maxWidth{
-    CGAffineTransform oldTransform = aView.transform;
-    
-    CGAffineTransform scaleTransform = CGAffineTransformIdentity;
-    if (!isnan(maxWidth) && maxWidth>0) {
-        CGFloat maxScale = maxWidth/CGRectGetWidth(aView.frame);
-        CGAffineTransform transformScale = CGAffineTransformMakeScale(maxScale, maxScale);
-        scaleTransform = CGAffineTransformConcat(oldTransform, transformScale);
-    
-    }
-    if(!CGAffineTransformEqualToTransform(scaleTransform, CGAffineTransformIdentity)){
-        aView.transform = scaleTransform;
-    }
-    
-    CGRect actureFrame = aView.frame; //���������������������frame
-    CGRect actureBounds= aView.bounds;//CGRectApplyAffineTransform();
-    
-    //begin
-    UIGraphicsBeginImageContextWithOptions(actureFrame.size, NO, 0.0);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    CGContextSaveGState(context);
-    //    CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1, -1);
-    CGContextTranslateCTM(context,actureFrame.size.width/2, actureFrame.size.height/2);
-    CGContextConcatCTM(context, aView.transform);
-    CGPoint anchorPoint = aView.layer.anchorPoint;
-    CGContextTranslateCTM(context,
-                          -actureBounds.size.width * anchorPoint.x,
-                          -actureBounds.size.height * anchorPoint.y);
-    if([aView respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
-    {
-        [aView drawViewHierarchyInRect:aView.bounds afterScreenUpdates:NO];
-    }
-    else
-    {
-        [aView.layer renderInContext:UIGraphicsGetCurrentContext()];
-    }
-    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    //end
-    aView.transform = oldTransform;
-    
-    return screenshot;
-}
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Color.h b/camerademo/camerademo/demo/UIImage/UIImage+Color.h
deleted file mode 100755
index 10fefa6..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Color.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-//  UIImage+Color.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/15.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (Color)
-/**
- *  @brief  ������������������������������
- *
- *  @param color ������
- *
- *  @return ������������
- */
-+ (UIImage *)imageWithColor:(UIColor *)color;
-/**
- *  @brief  ���������������������������
- *
- *  @param point ���������
- *
- *  @return ������
- */
-- (UIColor *)colorAtPoint:(CGPoint )point;
-//more accurate method ,colorAtPixel 1x1 pixel
-/**
- *  @brief  ������������������������
- *
- *  @param point ���������
- *
- *  @return ������
- */
-- (UIColor *)colorAtPixel:(CGPoint)point;
-/**
- *  @brief  ���������������������������������������
- *
- *  @return ������������������������
- */
-- (BOOL)hasAlphaChannel;
-
-/**
- *  @brief  ���������������
- *
- *  @param sourceImage ������
- *
- *  @return ������������������
- */
-+ (UIImage*)covertToGrayImageFromImage:(UIImage*)sourceImage;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Color.m b/camerademo/camerademo/demo/UIImage/UIImage+Color.m
deleted file mode 100755
index e005574..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Color.m
+++ /dev/null
@@ -1,175 +0,0 @@
-//
-//  UIImage+Color.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/15.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+Color.h"
-
-@implementation UIImage (Color)
-/**
- *  @brief  ������������������������������
- *
- *  @param color ������
- *
- *  @return ������������
- */
-+ (UIImage *)imageWithColor:(UIColor *)color {
-    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
-    UIGraphicsBeginImageContext(rect.size);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    CGContextSetFillColorWithColor(context, [color CGColor]);
-    CGContextFillRect(context, rect);
-    
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    
-    return image;
-}
-/**
- *  @brief  ���������������������������
- *
- *  @param point ���������
- *
- *  @return ������
- */
-- (UIColor *)colorAtPoint:(CGPoint )point
-{
-    if (point.x < 0 || point.y < 0) return nil;
-    
-    CGImageRef imageRef = self.CGImage;
-    NSUInteger width = CGImageGetWidth(imageRef);
-    NSUInteger height = CGImageGetHeight(imageRef);
-    if (point.x >= width || point.y >= height) return nil;
-    
-    unsigned char *rawData = malloc(height * width * 4);
-    if (!rawData) return nil;
-    
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-    NSUInteger bytesPerPixel = 4;
-    NSUInteger bytesPerRow = bytesPerPixel * width;
-    NSUInteger bitsPerComponent = 8;
-    CGContextRef context = CGBitmapContextCreate(rawData,
-                                                 width,
-                                                 height,
-                                                 bitsPerComponent,
-                                                 bytesPerRow,
-                                                 colorSpace,
-                                                 kCGImageAlphaPremultipliedLast
-                                                 | kCGBitmapByteOrder32Big);
-    if (!context) {
-        free(rawData);
-        return nil;
-    }
-    CGColorSpaceRelease(colorSpace);
-    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
-    CGContextRelease(context);
-    
-    int byteIndex = (bytesPerRow * point.y) + point.x * bytesPerPixel;
-    CGFloat red   = (rawData[byteIndex]     * 1.0) / 255.0;
-    CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0;
-    CGFloat blue  = (rawData[byteIndex + 2] * 1.0) / 255.0;
-    CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;
-    
-    UIColor *result = nil;
-    result = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
-    free(rawData);
-    return result;
-}
-/**
- *  @brief  ������������������������
- *
- *  @param point ���������
- *
- *  @return ������
- */
-- (UIColor *)colorAtPixel:(CGPoint)point
-{
-    // Cancel if point is outside image coordinates
-    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) {
-        return nil;
-    }
-    
-    // Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
-    // Reference: http://stackoverflow.com/questions/1042830/retrieving-a-pixel-alpha-value-for-a-uiimage
-    NSInteger pointX = trunc(point.x);
-    NSInteger pointY = trunc(point.y);
-    CGImageRef cgImage = self.CGImage;
-    NSUInteger width = self.size.width;
-    NSUInteger height = self.size.height;
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-    int bytesPerPixel = 4;
-    int bytesPerRow = bytesPerPixel * 1;
-    NSUInteger bitsPerComponent = 8;
-    unsigned char pixelData[4] = { 0, 0, 0, 0 };
-    CGContextRef context = CGBitmapContextCreate(pixelData,
-                                                 1,
-                                                 1,
-                                                 bitsPerComponent,
-                                                 bytesPerRow,
-                                                 colorSpace,
-                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
-    CGColorSpaceRelease(colorSpace);
-    CGContextSetBlendMode(context, kCGBlendModeCopy);
-    
-    // Draw the pixel we are interested in onto the bitmap context
-    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
-    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
-    CGContextRelease(context);
-    
-    // Convert color values [0..255] to floats [0.0..1.0]
-    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
-    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
-    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
-    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
-    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
-}
-/**
- *  @brief  ���������������������������������������
- *
- *  @return ������������������������
- */
-- (BOOL)hasAlphaChannel
-{
-    CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
-    return (alpha == kCGImageAlphaFirst ||
-            alpha == kCGImageAlphaLast ||
-            alpha == kCGImageAlphaPremultipliedFirst ||
-            alpha == kCGImageAlphaPremultipliedLast);
-}
-
-/**
- *  @brief  ���������������
- *
- *  @param sourceImage ������
- *
- *  @return ������������������
- */
-
-+ (UIImage*)covertToGrayImageFromImage:(UIImage*)sourceImage
-{
-    int width = sourceImage.size.width;
-    int height = sourceImage.size.height;
-    
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
-    CGContextRef context = CGBitmapContextCreate (nil,width,height,8,0,colorSpace,kCGImageAlphaNone);
-    CGColorSpaceRelease(colorSpace);
-    
-    if (context == NULL) {
-        return nil;
-    }
-    
-    CGContextDrawImage(context,CGRectMake(0, 0, width, height), sourceImage.CGImage);
-    CGImageRef contextRef = CGBitmapContextCreateImage(context);
-    UIImage *grayImage = [UIImage imageWithCGImage:contextRef];
-    CGContextRelease(context);
-    CGImageRelease(contextRef);
-    
-    return grayImage;
-}
-
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+FX.h b/camerademo/camerademo/demo/UIImage/UIImage+FX.h
deleted file mode 100755
index 1eacf3d..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+FX.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-//  UIImage+FX.h
-//
-//  Version 1.2.3
-//
-//  Created by Nick Lockwood on 31/10/2011.
-//  Copyright (c) 2011 Charcoal Design
-//
-//  Distributed under the permissive zlib License
-//  Get the latest version from here:
-//
-//  https://github.com/nicklockwood/FXImageView
-//
-//  This software is provided 'as-is', without any express or implied
-//  warranty.  In no event will the authors be held liable for any damages
-//  arising from the use of this software.
-//
-//  Permission is granted to anyone to use this software for any purpose,
-//  including commercial applications, and to alter it and redistribute it
-//  freely, subject to the following restrictions:
-//
-//  1. The origin of this software must not be misrepresented; you must not
-//  claim that you wrote the original software. If you use this software
-//  in a product, an acknowledgment in the product documentation would be
-//  appreciated but is not required.
-//
-//  2. Altered source versions must be plainly marked as such, and must not be
-//  misrepresented as being the original software.
-//
-//  3. This notice may not be removed or altered from any source distribution.
-//
-
-#import <UIKit/UIKit.h>
-
-
-@interface UIImage (FX)
-
-- (UIImage *)imageCroppedToRect:(CGRect)rect;
-- (UIImage *)imageScaledToSize:(CGSize)size;
-- (UIImage *)imageScaledToFitSize:(CGSize)size;
-- (UIImage *)imageScaledToFillSize:(CGSize)size;
-- (UIImage *)imageCroppedAndScaledToSize:(CGSize)size
-                             contentMode:(UIViewContentMode)contentMode
-                                padToFit:(BOOL)padToFit;
-
-- (UIImage *)reflectedImageWithScale:(CGFloat)scale;
-- (UIImage *)imageWithReflectionWithScale:(CGFloat)scale gap:(CGFloat)gap alpha:(CGFloat)alpha;
-- (UIImage *)imageWithShadowColor:(UIColor *)color offset:(CGSize)offset blur:(CGFloat)blur;
-- (UIImage *)imageWithCornerRadius:(CGFloat)radius;
-- (UIImage *)imageWithAlpha:(CGFloat)alpha;
-- (UIImage *)imageWithMask:(UIImage *)maskImage;
-
-- (UIImage *)maskImageFromImageAlpha;
-
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+FX.m b/camerademo/camerademo/demo/UIImage/UIImage+FX.m
deleted file mode 100755
index 904a1f3..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+FX.m
+++ /dev/null
@@ -1,426 +0,0 @@
-//
-//  UIImage+FX.m
-//
-//  Version 1.2.3
-//
-//  Created by Nick Lockwood on 31/10/2011.
-//  Copyright (c) 2011 Charcoal Design
-//
-//  Distributed under the permissive zlib License
-//  Get the latest version from here:
-//
-//  https://github.com/nicklockwood/FXImageView
-//
-//  This software is provided 'as-is', without any express or implied
-//  warranty.  In no event will the authors be held liable for any damages
-//  arising from the use of this software.
-//
-//  Permission is granted to anyone to use this software for any purpose,
-//  including commercial applications, and to alter it and redistribute it
-//  freely, subject to the following restrictions:
-//
-//  1. The origin of this software must not be misrepresented; you must not
-//  claim that you wrote the original software. If you use this software
-//  in a product, an acknowledgment in the product documentation would be
-//  appreciated but is not required.
-//
-//  2. Altered source versions must be plainly marked as such, and must not be
-//  misrepresented as being the original software.
-//
-//  3. This notice may not be removed or altered from any source distribution.
-//
-
-#import "UIImage+FX.h"
-
-@implementation UIImage (FX)
-
-- (UIImage *)imageCroppedToRect:(CGRect)rect
-{
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0f);
-    
-    //draw
-    [self drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageScaledToSize:(CGSize)size
-{   
-    //avoid redundant drawing
-    if (CGSizeEqualToSize(self.size, size))
-    {
-        return self;
-    }
-    
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
-    
-    //draw
-    [self drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageScaledToFitSize:(CGSize)size
-{
-    //calculate rect
-    CGFloat aspect = self.size.width / self.size.height;
-    if (size.width / aspect <= size.height)
-    {
-        return [self imageScaledToSize:CGSizeMake(size.width, size.width / aspect)];
-    }
-    else
-    {
-        return [self imageScaledToSize:CGSizeMake(size.height * aspect, size.height)];
-    }
-}
-
-- (UIImage *)imageScaledToFillSize:(CGSize)size
-{
-    if (CGSizeEqualToSize(self.size, size))
-    {
-        return self;
-    }
-    //calculate rect
-    CGFloat aspect = self.size.width / self.size.height;
-    if (size.width / aspect >= size.height)
-    {
-        return [self imageScaledToSize:CGSizeMake(size.width, size.width / aspect)];
-    }
-    else
-    {
-        return [self imageScaledToSize:CGSizeMake(size.height * aspect, size.height)];
-    }
-}
-
-- (UIImage *)imageCroppedAndScaledToSize:(CGSize)size
-                             contentMode:(UIViewContentMode)contentMode
-                                padToFit:(BOOL)padToFit;
-{
-    //calculate rect
-    CGRect rect = CGRectZero;
-    switch (contentMode)
-    {
-        case UIViewContentModeScaleAspectFit:
-        {
-            CGFloat aspect = self.size.width / self.size.height;
-            if (size.width / aspect <= size.height)
-            {
-                rect = CGRectMake(0.0f, (size.height - size.width / aspect) / 2.0f, size.width, size.width / aspect);
-            }
-            else
-            {
-                rect = CGRectMake((size.width - size.height * aspect) / 2.0f, 0.0f, size.height * aspect, size.height);
-            }
-            break;
-        }
-        case UIViewContentModeScaleAspectFill:
-        {
-            CGFloat aspect = self.size.width / self.size.height;
-            if (size.width / aspect >= size.height)
-            {
-                rect = CGRectMake(0.0f, (size.height - size.width / aspect) / 2.0f, size.width, size.width / aspect);
-            }
-            else
-            {
-                rect = CGRectMake((size.width - size.height * aspect) / 2.0f, 0.0f, size.height * aspect, size.height);
-            }
-            break;
-        }
-        case UIViewContentModeCenter:
-        {
-            rect = CGRectMake((size.width - self.size.width) / 2.0f, (size.height - self.size.height) / 2.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeTop:
-        {
-            rect = CGRectMake((size.width - self.size.width) / 2.0f, 0.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeBottom:
-        {
-            rect = CGRectMake((size.width - self.size.width) / 2.0f, size.height - self.size.height, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeLeft:
-        {
-            rect = CGRectMake(0.0f, (size.height - self.size.height) / 2.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeRight:
-        {
-            rect = CGRectMake(size.width - self.size.width, (size.height - self.size.height) / 2.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeTopLeft:
-        {
-            rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeTopRight:
-        {
-            rect = CGRectMake(size.width - self.size.width, 0.0f, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeBottomLeft:
-        {
-            rect = CGRectMake(0.0f, size.height - self.size.height, self.size.width, self.size.height);
-            break;
-        }
-        case UIViewContentModeBottomRight:
-        {
-            rect = CGRectMake(size.width - self.size.width, size.height - self.size.height, self.size.width, self.size.height);
-            break;
-        }  
-        default:
-        {
-            rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
-            break;
-        }
-    }
-    
-    if (!padToFit)
-    {
-        //remove padding
-        if (rect.size.width < size.width)
-        {
-            size.width = rect.size.width;
-            rect.origin.x = 0.0f;
-        }
-        if (rect.size.height < size.height)
-        {
-            size.height = rect.size.height;
-            rect.origin.y = 0.0f;
-        }
-    }
-    
-    //avoid redundant drawing
-    if (CGSizeEqualToSize(self.size, size))
-    {
-        return self;
-    }
-    
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
-    
-    //draw
-    [self drawInRect:rect];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-+ (CGImageRef)gradientMask
-{
-    static CGImageRef sharedMask = NULL;
-    if (sharedMask == NULL)
-    {
-        //create gradient mask
-        UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 256), YES, 0.0);
-        CGContextRef gradientContext = UIGraphicsGetCurrentContext();
-        CGFloat colors[] = {0.0, 1.0, 1.0, 1.0};
-        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
-        CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
-        CGPoint gradientStartPoint = CGPointMake(0, 0);
-        CGPoint gradientEndPoint = CGPointMake(0, 256);
-        CGContextDrawLinearGradient(gradientContext, gradient, gradientStartPoint,
-                                    gradientEndPoint, kCGGradientDrawsAfterEndLocation);
-        sharedMask = CGBitmapContextCreateImage(gradientContext);
-        CGGradientRelease(gradient);
-        CGColorSpaceRelease(colorSpace);
-        UIGraphicsEndImageContext();
-    }
-    return sharedMask;
-}
-
-- (UIImage *)reflectedImageWithScale:(CGFloat)scale
-{
-	//get reflection dimensions
-	CGFloat height = ceil(self.size.height * scale);
-	CGSize size = CGSizeMake(self.size.width, height);
-	CGRect bounds = CGRectMake(0.0f, 0.0f, size.width, size.height);
-	
-	//create drawing context
-	UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
-	CGContextRef context = UIGraphicsGetCurrentContext();
-	
-	//clip to gradient
-	CGContextClipToMask(context, bounds, [[self class] gradientMask]);
-	
-	//draw reflected image
-	CGContextScaleCTM(context, 1.0f, -1.0f);
-	CGContextTranslateCTM(context, 0.0f, -self.size.height);
-	[self drawInRect:CGRectMake(0.0f, 0.0f, self.size.width, self.size.height)];
-	
-	//capture resultant image
-	UIImage *reflection = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return reflection image
-	return reflection;
-}
-
-- (UIImage *)imageWithReflectionWithScale:(CGFloat)scale gap:(CGFloat)gap alpha:(CGFloat)alpha
-{
-    //get reflected image
-    UIImage *reflection = [self reflectedImageWithScale:scale];
-    CGFloat reflectionOffset = reflection.size.height + gap;
-    
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.size.width, self.size.height + reflectionOffset * 2.0f), NO, 0.0f);
-    
-    //draw reflection
-    [reflection drawAtPoint:CGPointMake(0.0f, reflectionOffset + self.size.height + gap) blendMode:kCGBlendModeNormal alpha:alpha];
-    
-    //draw image
-    [self drawAtPoint:CGPointMake(0.0f, reflectionOffset)];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageWithShadowColor:(UIColor *)color offset:(CGSize)offset blur:(CGFloat)blur
-{
-    //get size
-    //CGSize border = CGSizeMake(fabsf(offset.width) + blur, fabsf(offset.height) + blur);
-    CGSize border = CGSizeMake(fabs(offset.width) + blur, fabs(offset.height) + blur);
-
-    CGSize size = CGSizeMake(self.size.width + border.width * 2.0f, self.size.height + border.height * 2.0f);
-    
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    //set up shadow
-    CGContextSetShadowWithColor(context, offset, blur, color.CGColor);
-    
-    //draw with shadow
-    [self drawAtPoint:CGPointMake(border.width, border.height)];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageWithCornerRadius:(CGFloat)radius
-{
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    //clip image
-    CGContextBeginPath(context);
-    CGContextMoveToPoint(context, 0.0f, radius);
-    CGContextAddLineToPoint(context, 0.0f, self.size.height - radius);
-    CGContextAddArc(context, radius, self.size.height - radius, radius, M_PI, M_PI / 2.0f, 1);
-    CGContextAddLineToPoint(context, self.size.width - radius, self.size.height);
-    CGContextAddArc(context, self.size.width - radius, self.size.height - radius, radius, M_PI / 2.0f, 0.0f, 1);
-    CGContextAddLineToPoint(context, self.size.width, radius);
-    CGContextAddArc(context, self.size.width - radius, radius, radius, 0.0f, -M_PI / 2.0f, 1);
-    CGContextAddLineToPoint(context, radius, 0.0f);
-    CGContextAddArc(context, radius, radius, radius, -M_PI / 2.0f, M_PI, 1);
-    CGContextClip(context);
-    
-    //draw image
-    [self drawAtPoint:CGPointZero];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageWithAlpha:(CGFloat)alpha
-{
-    //create drawing context
-	UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
-    
-    //draw with alpha
-    [self drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:alpha];
-    
-    //capture resultant image
-	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-	UIGraphicsEndImageContext();
-	
-	//return image
-	return image;
-}
-
-- (UIImage *)imageWithMask:(UIImage *)maskImage;
-{
-    //create drawing context
-    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    //apply mask
-    CGContextClipToMask(context, CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), maskImage.CGImage);
-    
-    //draw image
-    [self drawAtPoint:CGPointZero];
-    
-    //capture resultant image
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    
-    //return image
-    return image;
-}
-
-- (UIImage *)maskImageFromImageAlpha
-{
-    //get dimensions
-    NSInteger width = CGImageGetWidth(self.CGImage);
-    NSInteger height = CGImageGetHeight(self.CGImage);
-    
-    //create alpha image
-    NSInteger bytesPerRow = ((width + 3) / 4) * 4;
-    void *data = calloc(bytesPerRow * height, sizeof(unsigned char *));
-    CGContextRef context = CGBitmapContextCreate(data, width, height, 8, bytesPerRow, NULL, kCGImageAlphaOnly);
-    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), self.CGImage);
-    
-    //invert alpha pixels
-    for (int y = 0; y < height; y++)
-    {
-        for (int x = 0; x < width; x++)
-        {
-            NSInteger index = y * bytesPerRow + x;
-            ((unsigned char *)data)[index] = 255 - ((unsigned char *)data)[index];
-        }
-    }
-    
-    //create mask image
-    CGImageRef maskRef = CGBitmapContextCreateImage(context);
-    CGContextRelease(context);
-    UIImage *mask = [UIImage imageWithCGImage:maskRef];
-    CGImageRelease(maskRef);
-    free(data);
-
-    //return image
-	return mask;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+FileName.h b/camerademo/camerademo/demo/UIImage/UIImage+FileName.h
deleted file mode 100755
index 6e881f3..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+FileName.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-//  UIImage+FileName.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/15.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (FileName)
-/**
- *  @brief  ������bundle���������������������������
- *
- *  @param name ���������
- *
- *  @return ������������������
- */
-+ (UIImage *)imageWithFileName:(NSString *)name;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+FileName.m b/camerademo/camerademo/demo/UIImage/UIImage+FileName.m
deleted file mode 100755
index 6a468ee..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+FileName.m
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-//  UIImage+FileName.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/15.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-#import "UIImage+FileName.h"
-
-
-@implementation UIImage (FileName)
-/**
- *  @brief  ������bundle���������������������������
- *
- *  @param name ���������
- *
- *  @return ������������������
- */
-+ (UIImage *)imageWithFileName:(NSString *)name {
-    NSString *extension = @"png";
-    
-    NSArray *components = [name componentsSeparatedByString:@"."];
-    if ([components count] >= 2) {
-        NSUInteger lastIndex = components.count - 1;
-        extension = [components objectAtIndex:lastIndex];
-        
-        name = [name substringToIndex:(name.length-(extension.length+1))];
-    }
-    
-    // ���������Retina���������������������������������������Retina���������������������������������
-    if ([UIScreen mainScreen].scale == 2.0) {
-        name = [name stringByAppendingString:@"@2x"];
-        
-        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
-        if (path != nil) {
-            return [UIImage imageWithContentsOfFile:path];
-        }
-    }
-    
-    if ([UIScreen mainScreen].scale == 3.0) {
-        name = [name stringByAppendingString:@"@3x"];
-        
-        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
-        if (path != nil) {
-            return [UIImage imageWithContentsOfFile:path];
-        }
-    }
-    
-    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
-    if (path) {
-        return [UIImage imageWithContentsOfFile:path];
-    }
-    
-    return nil;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+GIF.h b/camerademo/camerademo/demo/UIImage/UIImage+GIF.h
deleted file mode 100755
index 084f424..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+GIF.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-//  UIImage+GIF.h
-//  LBGIFImage
-//
-//  Created by Laurin Brandner on 06.01.12.
-//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (GIF)
-
-+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;
-
-+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;
-
-- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+GIF.m b/camerademo/camerademo/demo/UIImage/UIImage+GIF.m
deleted file mode 100755
index a703637..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+GIF.m
+++ /dev/null
@@ -1,158 +0,0 @@
-//
-//  UIImage+GIF.m
-//  LBGIFImage
-//
-//  Created by Laurin Brandner on 06.01.12.
-//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
-//
-
-#import "UIImage+GIF.h"
-#import <ImageIO/ImageIO.h>
-
-@implementation UIImage (GIF)
-
-+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
-    if (!data) {
-        return nil;
-    }
-
-    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
-
-    size_t count = CGImageSourceGetCount(source);
-
-    UIImage *animatedImage;
-
-    if (count <= 1) {
-        animatedImage = [[UIImage alloc] initWithData:data];
-    }
-    else {
-        NSMutableArray *images = [NSMutableArray array];
-
-        NSTimeInterval duration = 0.0f;
-
-        for (size_t i = 0; i < count; i++) {
-            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
-
-            duration += [self sd_frameDurationAtIndex:i source:source];
-
-            [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
-
-            CGImageRelease(image);
-        }
-
-        if (!duration) {
-            duration = (1.0f / 10.0f) * count;
-        }
-
-        animatedImage = [UIImage animatedImageWithImages:images duration:duration];
-    }
-
-    CFRelease(source);
-
-    return animatedImage;
-}
-
-+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
-    float frameDuration = 0.1f;
-    CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
-    NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
-    NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
-
-    NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
-    if (delayTimeUnclampedProp) {
-        frameDuration = [delayTimeUnclampedProp floatValue];
-    }
-    else {
-
-        NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
-        if (delayTimeProp) {
-            frameDuration = [delayTimeProp floatValue];
-        }
-    }
-
-    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
-    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
-    // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
-    // for more information.
-
-    if (frameDuration < 0.011f) {
-        frameDuration = 0.100f;
-    }
-
-    CFRelease(cfFrameProperties);
-    return frameDuration;
-}
-
-+ (UIImage *)sd_animatedGIFNamed:(NSString *)name {
-    CGFloat scale = [UIScreen mainScreen].scale;
-
-    if (scale > 1.0f) {
-        NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"];
-
-        NSData *data = [NSData dataWithContentsOfFile:retinaPath];
-
-        if (data) {
-            return [UIImage sd_animatedGIFWithData:data];
-        }
-
-        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
-
-        data = [NSData dataWithContentsOfFile:path];
-
-        if (data) {
-            return [UIImage sd_animatedGIFWithData:data];
-        }
-
-        return [UIImage imageNamed:name];
-    }
-    else {
-        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
-
-        NSData *data = [NSData dataWithContentsOfFile:path];
-
-        if (data) {
-            return [UIImage sd_animatedGIFWithData:data];
-        }
-
-        return [UIImage imageNamed:name];
-    }
-}
-
-- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size {
-    if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) {
-        return self;
-    }
-
-    CGSize scaledSize = size;
-    CGPoint thumbnailPoint = CGPointZero;
-
-    CGFloat widthFactor = size.width / self.size.width;
-    CGFloat heightFactor = size.height / self.size.height;
-    CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;
-    scaledSize.width = self.size.width * scaleFactor;
-    scaledSize.height = self.size.height * scaleFactor;
-
-    if (widthFactor > heightFactor) {
-        thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;
-    }
-    else if (widthFactor < heightFactor) {
-        thumbnailPoint.x = (size.width - scaledSize.width) * 0.5;
-    }
-
-    NSMutableArray *scaledImages = [NSMutableArray array];
-
-    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
-
-    for (UIImage *image in self.images) {
-        [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];
-        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
-
-        [scaledImages addObject:newImage];
-    }
-
-    UIGraphicsEndImageContext();
-
-    return [UIImage animatedImageWithImages:scaledImages duration:self.duration];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Merge.h b/camerademo/camerademo/demo/UIImage/UIImage+Merge.h
deleted file mode 100755
index a7eeb5c..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Merge.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-//  UIImage+Merge.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/30.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (Merge)
-/**
- *  @brief  ������������������
- *
- *  @param firstImage  ������������
- *  @param secondImage ������������
- *
- *  @return ���������������
- */
-+ (UIImage*)mergeImage:(UIImage*)firstImage withImage:(UIImage*)secondImage;
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Merge.m b/camerademo/camerademo/demo/UIImage/UIImage+Merge.m
deleted file mode 100755
index b3dc743..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Merge.m
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-//  UIImage+Merge.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 14/12/30.
-//  Copyright (c) 2014��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+Merge.h"
-
-@implementation UIImage (Merge)
-/**
- *  @brief  ������������������
- *
- *  @param firstImage  ������������
- *  @param secondImage ������������
- *
- *  @return ���������������
- */
-+ (UIImage*)mergeImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
-    CGImageRef firstImageRef = firstImage.CGImage;
-    CGFloat firstWidth = CGImageGetWidth(firstImageRef);
-    CGFloat firstHeight = CGImageGetHeight(firstImageRef);
-    CGImageRef secondImageRef = secondImage.CGImage;
-    CGFloat secondWidth = CGImageGetWidth(secondImageRef);
-    CGFloat secondHeight = CGImageGetHeight(secondImageRef);
-    CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
-    UIGraphicsBeginImageContext(mergedSize);
-    [firstImage drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
-    [secondImage drawInRect:CGRectMake(0, 0, secondWidth, secondHeight)];
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    return image;
-}
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Orientation.h b/camerademo/camerademo/demo/UIImage/UIImage+Orientation.h
deleted file mode 100755
index 89a3fd9..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Orientation.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-//  UIImage+Orientation.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/4.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-//CGFloat DegreesToRadiansForOrientation(CGFloat degrees) {return degrees * M_PI / 180;};
-//CGFloat RadiansToDegreesForOrientation(CGFloat radians) {return radians * 180/M_PI;};
-@interface UIImage (Orientation)
-/**
- *  @brief  ���������������������
- *
- *  @param srcImg ������
- *
- *  @return ������������������������
- */
-+ (UIImage *)fixOrientation:(UIImage *)srcImg;
-/**
- *  @brief  ������������
- *
- *  @param degrees ������
- *
- *  @return ���������������
- */
-- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;
-
-/**
- *  @brief  ������������
- *
- *  @param degrees ������
- *
- *  @return ���������������
- */
-- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
-
-/**
- *  @brief  ������������
- *
- *  @return  ������������������
- */
-- (UIImage *)flipVertical;
-/**
- *  @brief  ������������
- *
- *  @return ������������������
- */
-- (UIImage *)flipHorizontal;
-
-/**
- *  @brief  ���������������
- *
- *  @param degrees ������
- *
- *  @return ������
- */
-+(CGFloat)degreesToRadians:(CGFloat)degrees;
-/**
- *  @brief  ���������������
- *
- *  @param radians ������
- *
- *  @return ������
- */
-+(CGFloat)radiansToDegrees:(CGFloat)radians;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Orientation.m b/camerademo/camerademo/demo/UIImage/UIImage+Orientation.m
deleted file mode 100755
index 98a1a98..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Orientation.m
+++ /dev/null
@@ -1,181 +0,0 @@
-//
-//  UIImage+Orientation.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/4.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+Orientation.h"
-
-@implementation UIImage (Orientation)
-/**
- *  @brief  ���������������������
- *
- *  @param srcImg ������
- *
- *  @return ������������������������
- */
-+ (UIImage *)fixOrientation:(UIImage *)srcImg {
-    if (srcImg.imageOrientation == UIImageOrientationUp) return srcImg;
-    CGAffineTransform transform = CGAffineTransformIdentity;
-    switch (srcImg.imageOrientation) {
-        case UIImageOrientationDown:
-        case UIImageOrientationDownMirrored:
-            transform = CGAffineTransformTranslate(transform, srcImg.size.width, srcImg.size.height);
-            transform = CGAffineTransformRotate(transform, M_PI);
-            break;
-        case UIImageOrientationLeft:
-        case UIImageOrientationLeftMirrored:
-            transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0);
-            transform = CGAffineTransformRotate(transform, M_PI_2);
-            break;
-        case UIImageOrientationRight:
-        case UIImageOrientationRightMirrored:
-            transform = CGAffineTransformTranslate(transform, 0, srcImg.size.height);
-            transform = CGAffineTransformRotate(transform, -M_PI_2);
-            break;
-        case UIImageOrientationUp:
-        case UIImageOrientationUpMirrored:
-            break;
-    }
-    switch (srcImg.imageOrientation) {
-        case UIImageOrientationUpMirrored:
-        case UIImageOrientationDownMirrored:
-            transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0);
-            transform = CGAffineTransformScale(transform, -1, 1);
-            break;
-        case UIImageOrientationLeftMirrored:
-        case UIImageOrientationRightMirrored:
-            transform = CGAffineTransformTranslate(transform, srcImg.size.height, 0);
-            transform = CGAffineTransformScale(transform, -1, 1);
-            break;
-        case UIImageOrientationUp:
-        case UIImageOrientationDown:
-        case UIImageOrientationLeft:
-        case UIImageOrientationRight:
-            break;
-    }
-    CGContextRef ctx = CGBitmapContextCreate(NULL, srcImg.size.width, srcImg.size.height,
-                                             CGImageGetBitsPerComponent(srcImg.CGImage), 0,
-                                             CGImageGetColorSpace(srcImg.CGImage),
-                                             CGImageGetBitmapInfo(srcImg.CGImage));
-    CGContextConcatCTM(ctx, transform);
-    switch (srcImg.imageOrientation) {
-        case UIImageOrientationLeft:
-        case UIImageOrientationLeftMirrored:
-        case UIImageOrientationRight:
-        case UIImageOrientationRightMirrored:
-            CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.height,srcImg.size.width), srcImg.CGImage);
-            break;
-        default:
-            CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.width,srcImg.size.height), srcImg.CGImage);
-            break;
-    }
-    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
-    UIImage *img = [UIImage imageWithCGImage:cgimg];
-    CGContextRelease(ctx);
-    CGImageRelease(cgimg);
-    return img;
-}
-
-- (UIImage *)flip:(BOOL)isHorizontal {
-    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
-    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
-
-    CGContextRef ctx = UIGraphicsGetCurrentContext();
-    CGContextClipToRect(ctx, rect);
-    if (isHorizontal) {
-        CGContextRotateCTM(ctx, M_PI);
-        CGContextTranslateCTM(ctx, -rect.size.width, -rect.size.height);
-    }
-    CGContextDrawImage(ctx, rect, self.CGImage);
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    return image;
-}
-/**
- *  @brief  ������������
- *
- *  @return  ������������������
- */
-- (UIImage *)flipVertical {
-    return [self flip:NO];
-}
-/**
- *  @brief  ������������
- *
- *  @return ������������������
- */
-- (UIImage *)flipHorizontal {
-    return [self flip:YES];
-}
-/**
- *  @brief  ������������
- *
- *  @param degrees ������
- *
- *  @return ���������������
- */
-- (UIImage *)imageRotatedByRadians:(CGFloat)radians
-{
-    return [self imageRotatedByDegrees:[UIImage radiansToDegrees:radians]];
-}
-/**
- *  @brief  ������������
- *
- *  @param degrees ���
- *
- *  @return ���������������
- */
-- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
-{
-    // calculate the size of the rotated view's containing box for our drawing space
-    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
-    CGAffineTransform t = CGAffineTransformMakeRotation([UIImage degreesToRadians:degrees]);
-    rotatedViewBox.transform = t;
-    CGSize rotatedSize = rotatedViewBox.frame.size;
-    
-    // Create the bitmap context
-    UIGraphicsBeginImageContext(rotatedSize);
-    CGContextRef bitmap = UIGraphicsGetCurrentContext();
-    
-    // Move the origin to the middle of the image so we will rotate and scale around the center.
-    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
-    
-    //   // Rotate the image context
-    CGContextRotateCTM(bitmap, [UIImage degreesToRadians:degrees]);
-    
-    // Now, draw the rotated/scaled image into the context
-    CGContextScaleCTM(bitmap, 1.0, -1.0);
-    CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
-    
-    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    return newImage;
-    
-}
-
-/**
- *  @brief  ���������������
- *
- *  @param degrees ������
- *
- *  @return ������
- */
-+(CGFloat)degreesToRadians:(CGFloat)degrees
-{
-    return degrees * M_PI / 180;
-}
-/**
- *  @brief  ���������������
- *
- *  @param radians ������
- *
- *  @return ������
- */
-+(CGFloat)radiansToDegrees:(CGFloat)radians
-{
-    return radians * 180/M_PI;
-}
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+PDF.h b/camerademo/camerademo/demo/UIImage/UIImage+PDF.h
deleted file mode 100755
index 27db567..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+PDF.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-//  UIImage+PDF.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/5/22.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage (PDF)
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+PDF.m b/camerademo/camerademo/demo/UIImage/UIImage+PDF.m
deleted file mode 100755
index e6ca42f..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+PDF.m
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-//  UIImage+PDF.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/5/22.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+PDF.h"
-
-@implementation UIImage (PDF)
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.h b/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.h
deleted file mode 100755
index 8d4d1f2..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-//  UIImage+RemoteSize.h
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/27.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-typedef void (^UIImageSizeRequestCompleted) (NSURL* imgURL, CGSize size);
-
-@interface UIImage (RemoteSize)
-/**
- *  @brief ���������������������������
- *
- *  @param imgURL     ������url
- *  @param completion ������������
- */
-+ (void)requestSizeNoHeader:(NSURL*)imgURL completion:(UIImageSizeRequestCompleted)completion;
-/**
- *  @brief  ���header������������������������������ (���������������������)
- *
- *  @param imgURL     ������url
- *  @param completion ������������
- */
-//+ (void)requestSizeWithHeader:(NSURL*)imgURL completion:(UIImageSizeRequestCompleted)completion;
-
-@end
\ No newline at end of file
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.m b/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.m
deleted file mode 100755
index 82d4085..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+RemoteSize.m
+++ /dev/null
@@ -1,270 +0,0 @@
-//
-//  UIImage+RemoteSize.m
-//  iOS-Categories (https://github.com/shaojiankui/iOS-Categories)
-//
-//  Created by Jakey on 15/1/27.
-//  Copyright (c) 2015��� www.skyfox.org. All rights reserved.
-//
-
-#import "UIImage+RemoteSize.h"
-
-#import <objc/runtime.h>
-
-static char *kSizeRequestDataKey = "NSURL.sizeRequestData";
-static char *kSizeRequestTypeKey = "NSURL.sizeRequestType";
-static char *kSizeRequestCompletionKey = "NSURL.sizeRequestCompletion";
-
-typedef uint32_t dword;
-
-@interface NSURL (RemoteSize)
-@property (nonatomic, strong) NSMutableData* sizeRequestData;
-@property (nonatomic, strong) NSString* sizeRequestType;
-@property (nonatomic, copy) UIImageSizeRequestCompleted sizeRequestCompletion;
-@end
-
-@implementation NSURL (RemoteSize)
-
-- (void)setSizeRequestCompletion: (UIImageSizeRequestCompleted) block {
-    objc_setAssociatedObject(self, &kSizeRequestCompletionKey, block, OBJC_ASSOCIATION_COPY);
-}
-
-- (UIImageSizeRequestCompleted)sizeRequestCompletion {
-    return objc_getAssociatedObject(self, &kSizeRequestCompletionKey);
-}
-
-- (void)setSizeRequestData:(NSMutableData *)sizeRequestData {
-    objc_setAssociatedObject(self, &kSizeRequestDataKey, sizeRequestData, OBJC_ASSOCIATION_RETAIN);
-}
-
-- (NSMutableData*)sizeRequestData {
-    return objc_getAssociatedObject(self, &kSizeRequestDataKey);
-}
-
-- (void)setSizeRequestType:(NSString *)sizeRequestType {
-    objc_setAssociatedObject(self, &kSizeRequestTypeKey, sizeRequestType, OBJC_ASSOCIATION_RETAIN);
-}
-
-- (NSString*)sizeRequestType {
-    return objc_getAssociatedObject(self, &kSizeRequestTypeKey);
-}
-
-#pragma mark - NSURLConnectionDelegate
-- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response {
-    [self.sizeRequestData setLength: 0];    //Redirected => reset data
-}
-
-- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData *)data {
-    NSMutableData* receivedData = self.sizeRequestData;
-    
-    if( !receivedData ) {
-        receivedData = [NSMutableData data];
-        self.sizeRequestData = receivedData;
-    }
-    
-    [receivedData appendData: data];
-    
-    //Parse metadata
-    const unsigned char* cString = [receivedData bytes];
-    const NSInteger length = [receivedData length];
-    
-    const char pngSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-    const char bmpSignature[2] = {66, 77};
-    const char gifSignature[2] = {71, 73};
-    const char jpgSignature[2] = {255, 216};
-    
-    if(!self.sizeRequestType ) {
-        if( memcmp(pngSignature, cString, 8) == 0 ) {
-            self.sizeRequestType = @"PNG";
-        }
-        else if( memcmp(bmpSignature, cString, 2) == 0 ) {
-            self.sizeRequestType = @"BMP";
-        }
-        else if( memcmp(jpgSignature, cString, 2) == 0 ) {
-            self.sizeRequestType = @"JPG";
-        }
-        else if( memcmp(gifSignature, cString, 2) == 0 ) {
-            self.sizeRequestType = @"GIF";
-        }
-    }
-    
-    if( [self.sizeRequestType isEqualToString: @"PNG"] ) {
-        char type[5];
-        int offset = 8;
-        
-        dword chunkSize = 0;
-        int chunkSizeSize = sizeof(chunkSize);
-        
-        if( offset+chunkSizeSize > length )
-            return;
-        
-        memcpy(&chunkSize, cString+offset, chunkSizeSize);
-        chunkSize = OSSwapInt32(chunkSize);
-        offset += chunkSizeSize;
-        
-        if( offset + chunkSize > length )
-            return;
-        
-        memcpy(&type, cString+offset, 4); type[4]='\0';
-        offset += 4;
-        
-        if( strcmp(type, "IHDR") == 0 ) {   //Should always be first
-            dword width = 0, height = 0;
-            memcpy(&width, cString+offset, 4);
-            offset += 4;
-            width = OSSwapInt32(width);
-            
-            memcpy(&height, cString+offset, 4);
-            offset += 4;
-            height = OSSwapInt32(height);
-            
-            if( self.sizeRequestCompletion ) {
-                self.sizeRequestCompletion(self, CGSizeMake(width, height));
-            }
-            
-            self.sizeRequestCompletion = nil;
-            
-            [connection cancel];
-        }
-    }
-    else if( [self.sizeRequestType isEqualToString: @"BMP"] ) {
-        int offset = 18;
-        dword width = 0, height = 0;
-        memcpy(&width, cString+offset, 4);
-        offset += 4;
-        
-        memcpy(&height, cString+offset, 4);
-        offset += 4;
-        
-        if( self.sizeRequestCompletion ) {
-            self.sizeRequestCompletion(self, CGSizeMake(width, height));
-        }
-        
-        self.sizeRequestCompletion = nil;
-        
-        [connection cancel];
-    }
-    else if( [self.sizeRequestType isEqualToString: @"JPG"] ) {
-        int offset = 4;
-        dword block_length = cString[offset]*256 + cString[offset+1];
-        
-        while (offset<length) {
-            offset += block_length;
-            
-            if( offset >= length )
-                break;
-            if( cString[offset] != 0xFF )
-                break;
-            if( cString[offset+1] == 0xC0 ||
-               cString[offset+1] == 0xC1 ||
-               cString[offset+1] == 0xC2 ||
-               cString[offset+1] == 0xC3 ||
-               cString[offset+1] == 0xC5 ||
-               cString[offset+1] == 0xC6 ||
-               cString[offset+1] == 0xC7 ||
-               cString[offset+1] == 0xC9 ||
-               cString[offset+1] == 0xCA ||
-               cString[offset+1] == 0xCB ||
-               cString[offset+1] == 0xCD ||
-               cString[offset+1] == 0xCE ||
-               cString[offset+1] == 0xCF ) {
-                
-                dword width = 0, height = 0;
-                
-                height = cString[offset+5]*256 + cString[offset+6];
-                width = cString[offset+7]*256 + cString[offset+8];
-                
-                if( self.sizeRequestCompletion ) {
-                    self.sizeRequestCompletion(self, CGSizeMake(width, height));
-                }
-                
-                self.sizeRequestCompletion = nil;
-                
-                [connection cancel];
-                
-            }
-            else {
-                offset += 2;
-                block_length = cString[offset]*256 + cString[offset+1];
-            }
-            
-        }
-    }
-    else if( [self.sizeRequestType isEqualToString: @"GIF"] ) {
-        int offset = 6;
-        dword width = 0, height = 0;
-        memcpy(&width, cString+offset, 2);
-        offset += 2;
-        
-        memcpy(&height, cString+offset, 2);
-        offset += 2;
-        
-        if( self.sizeRequestCompletion ) {
-            self.sizeRequestCompletion(self, CGSizeMake(width, height));
-        }
-        
-        self.sizeRequestCompletion = nil;
-        
-        [connection cancel];
-    }
-}
-
--(void)connection:(NSURLConnection*)connection didFailWithError:(NSError *)error {
-    if( self.sizeRequestCompletion )
-        self.sizeRequestCompletion(self, CGSizeZero);
-}
-
--(NSCachedURLResponse*)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
-    return cachedResponse;
-}
-
-- (void)connectionDidFinishLoading: (NSURLConnection *)connection {
-    // Basically, we failed to obtain the image size using metadata and the
-    // entire image was downloaded...
-    
-    if(!self.sizeRequestData.length) {
-        self.sizeRequestData = nil;
-    }
-    else {
-        //Try parse to UIImage
-        UIImage* image = [UIImage imageWithData: self.sizeRequestData];
-        
-        if( self.sizeRequestCompletion && image) {
-            self.sizeRequestCompletion(self, [image size]);
-            return;
-        }
-    }
-    
-    self.sizeRequestCompletion(self, CGSizeZero);
-}
-
-@end
-
-@implementation UIImage (RemoteSize)
-
-+ (void)requestSizeNoHeader:(NSURL*)imgURL completion:(UIImageSizeRequestCompleted)completion{
-    
-    if([imgURL isFileURL] ) {
-        //Load from file stream
-    }
-    else {
-        imgURL.sizeRequestCompletion = completion;
-        
-        NSURLRequest* request = [NSURLRequest requestWithURL:imgURL];
-        NSURLConnection* conn = [NSURLConnection connectionWithRequest: request delegate: imgURL];
-        [conn scheduleInRunLoop: [NSRunLoop mainRunLoop] forMode: NSDefaultRunLoopMode];
-        [conn start];
-    }
-}
-
-
-+ (void)requestSizeWithHeader:(NSURL*)imgURL completion:(UIImageSizeRequestCompleted)completion{
-//        NSURLRequest* request = [NSURLRequest requestWithURL:imgURL];
-//
-//        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *resp, NSData *d, NSError *e) {
-//            NSLog(@"respone%@", [(NSHTTPURLResponse*)resp allHeaderFields]);
-//    
-//            
-//        }];
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Resize.h b/camerademo/camerademo/demo/UIImage/UIImage+Resize.h
deleted file mode 100755
index 64610b1..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Resize.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// UIImage+Resize.h
-// Created by Trevor Harmon on 8/5/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-// Extends the UIImage class to support resizing/cropping
-#import <UIKit/UIKit.h>
-
-@interface UIImage (Resize)
-
-- (UIImage *)croppedImage:(CGRect)bounds;
-- (UIImage *)thumbnailImage:(NSInteger)thumbnailSize
-          transparentBorder:(NSUInteger)borderSize
-               cornerRadius:(NSUInteger)cornerRadius
-       interpolationQuality:(CGInterpolationQuality)quality;
-- (UIImage *)resizedImage:(CGSize)newSize
-     interpolationQuality:(CGInterpolationQuality)quality;
-- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode
-                                  bounds:(CGSize)bounds
-                    interpolationQuality:(CGInterpolationQuality)quality;
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Resize.m b/camerademo/camerademo/demo/UIImage/UIImage+Resize.m
deleted file mode 100755
index affbf31..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Resize.m
+++ /dev/null
@@ -1,200 +0,0 @@
-// UIImage+Resize.m
-// Created by Trevor Harmon on 8/5/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-#import "UIImage+Resize.h"
-#import "UIImage+RoundedCorner.h"
-#import "UIImage+Alpha.h"
-
-// Private helper methods
-@interface UIImage (ResizePrivateMethods)
-- (UIImage *)resizedImage:(CGSize)newSize
-                transform:(CGAffineTransform)transform
-           drawTransposed:(BOOL)transpose
-     interpolationQuality:(CGInterpolationQuality)quality;
-- (CGAffineTransform)transformForOrientation:(CGSize)newSize;
-@end
-
-@implementation UIImage (Resize)
-
-// Returns a copy of this image that is cropped to the given bounds.
-// The bounds will be adjusted using CGRectIntegral.
-// This method ignores the image's imageOrientation setting.
-- (UIImage *)croppedImage:(CGRect)bounds {
-    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
-    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
-    CGImageRelease(imageRef);
-    return croppedImage;
-}
-
-// Returns a copy of this image that is squared to the thumbnail size.
-// If transparentBorder is non-zero, a transparent border of the given size will be added around the edges of the thumbnail. (Adding a transparent border of at least one pixel in size has the side-effect of antialiasing the edges of the image when rotating it using Core Animation.)
-- (UIImage *)thumbnailImage:(NSInteger)thumbnailSize
-          transparentBorder:(NSUInteger)borderSize
-               cornerRadius:(NSUInteger)cornerRadius
-       interpolationQuality:(CGInterpolationQuality)quality {
-    UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill
-                                                       bounds:CGSizeMake(thumbnailSize, thumbnailSize)
-                                         interpolationQuality:quality];
-    
-    // Crop out any part of the image that's larger than the thumbnail size
-    // The cropped rect must be centered on the resized image
-    // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked
-    CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2),
-                                 round((resizedImage.size.height - thumbnailSize) / 2),
-                                 thumbnailSize,
-                                 thumbnailSize);
-    UIImage *croppedImage = [resizedImage croppedImage:cropRect];
-    
-    UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage;
-
-    return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize];
-}
-
-// Returns a rescaled copy of the image, taking into account its orientation
-// The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter
-- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
-    BOOL drawTransposed;
-    
-    switch (self.imageOrientation) {
-        case UIImageOrientationLeft:
-        case UIImageOrientationLeftMirrored:
-        case UIImageOrientationRight:
-        case UIImageOrientationRightMirrored:
-            drawTransposed = YES;
-            break;
-            
-        default:
-            drawTransposed = NO;
-    }
-    
-    return [self resizedImage:newSize
-                    transform:[self transformForOrientation:newSize]
-               drawTransposed:drawTransposed
-         interpolationQuality:quality];
-}
-
-// Resizes the image according to the given content mode, taking into account the image's orientation
-- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode
-                                  bounds:(CGSize)bounds
-                    interpolationQuality:(CGInterpolationQuality)quality {
-    CGFloat horizontalRatio = bounds.width / self.size.width;
-    CGFloat verticalRatio = bounds.height / self.size.height;
-    CGFloat ratio;
-    
-    switch (contentMode) {
-        case UIViewContentModeScaleAspectFill:
-            ratio = MAX(horizontalRatio, verticalRatio);
-            break;
-            
-        case UIViewContentModeScaleAspectFit:
-            ratio = MIN(horizontalRatio, verticalRatio);
-            break;
-            
-        default:
-            [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %@", @(contentMode)];
-    }
-    
-    CGSize newSize = CGSizeMake(round(self.size.width * ratio), round(self.size.height * ratio));
-    
-    return [self resizedImage:newSize interpolationQuality:quality];
-}
-
-#pragma mark -
-#pragma mark Private helper methods
-
-// Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size
-// The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation
-// If the new size is not integral, it will be rounded up
-- (UIImage *)resizedImage:(CGSize)newSize
-                transform:(CGAffineTransform)transform
-           drawTransposed:(BOOL)transpose
-     interpolationQuality:(CGInterpolationQuality)quality {
-    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
-    CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
-    CGImageRef imageRef = self.CGImage;
-    
-    // Build a context that's the same dimensions as the new size
-	uint32_t bitmapInfo = CGImageGetBitmapInfo(imageRef);
-	if((bitmapInfo == kCGImageAlphaLast) || (bitmapInfo == kCGImageAlphaNone))
-		bitmapInfo = kCGImageAlphaNoneSkipLast;
-		
-    
-    
-    CGContextRef bitmap = CGBitmapContextCreate(NULL,
-                                                newRect.size.width,
-                                                newRect.size.height,
-                                                CGImageGetBitsPerComponent(imageRef),
-                                                0,
-                                                CGImageGetColorSpace(imageRef),
-                                                bitmapInfo);
-    
-    // Rotate and/or flip the image if required by its orientation
-    CGContextConcatCTM(bitmap, transform);
-    
-    // Set the quality level to use when rescaling
-    CGContextSetInterpolationQuality(bitmap, quality);
-    
-    // Draw into the context; this scales the image
-    CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
-    
-    // Get the resized image from the context and a UIImage
-    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
-    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
-    
-    // Clean up
-    CGContextRelease(bitmap);
-    CGImageRelease(newImageRef);
-    
-    return newImage;
-}
-
-// Returns an affine transform that takes into account the image orientation when drawing a scaled image
-- (CGAffineTransform)transformForOrientation:(CGSize)newSize {
-    CGAffineTransform transform = CGAffineTransformIdentity;
-    
-    switch (self.imageOrientation) {
-        case UIImageOrientationDown:           // EXIF = 3
-        case UIImageOrientationDownMirrored:   // EXIF = 4
-            transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height);
-            transform = CGAffineTransformRotate(transform, M_PI);
-            break;
-            
-        case UIImageOrientationLeft:           // EXIF = 6
-        case UIImageOrientationLeftMirrored:   // EXIF = 5
-            transform = CGAffineTransformTranslate(transform, newSize.width, 0);
-            transform = CGAffineTransformRotate(transform, M_PI_2);
-            break;
-            
-        case UIImageOrientationRight:          // EXIF = 8
-        case UIImageOrientationRightMirrored:  // EXIF = 7
-            transform = CGAffineTransformTranslate(transform, 0, newSize.height);
-            transform = CGAffineTransformRotate(transform, -M_PI_2);
-            break;
-
-        default:
-            break;
-    }
-    
-    switch (self.imageOrientation) {
-        case UIImageOrientationUpMirrored:     // EXIF = 2
-        case UIImageOrientationDownMirrored:   // EXIF = 4
-            transform = CGAffineTransformTranslate(transform, newSize.width, 0);
-            transform = CGAffineTransformScale(transform, -1, 1);
-            break;
-            
-        case UIImageOrientationLeftMirrored:   // EXIF = 5
-        case UIImageOrientationRightMirrored:  // EXIF = 7
-            transform = CGAffineTransformTranslate(transform, newSize.height, 0);
-            transform = CGAffineTransformScale(transform, -1, 1);
-            break;
-            
-        default:
-            break;
-    }
-    
-    return transform;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.h b/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.h
deleted file mode 100755
index f9d9803..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// UIImage+RoundedCorner.h
-// Created by Trevor Harmon on 9/20/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-// Extends the UIImage class to support making rounded corners
-#import <UIKit/UIKit.h>
-@interface UIImage (RoundedCorner)
-- (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize;
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.m b/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.m
deleted file mode 100755
index f917f2c..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+RoundedCorner.m
+++ /dev/null
@@ -1,79 +0,0 @@
-// UIImage+RoundedCorner.m
-// Created by Trevor Harmon on 9/20/09.
-// Free for personal or commercial use, with or without modification.
-// No warranty is expressed or implied.
-
-#import "UIImage+RoundedCorner.h"
-#import "UIImage+Alpha.h"
-
-// Private helper methods
-@interface UIImage (RoundedCornerPrivateMethods)
-- (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight;
-@end
-
-@implementation UIImage (RoundedCorner)
-
-// Creates a copy of this image with rounded corners
-// If borderSize is non-zero, a transparent border of the given size will also be added
-// Original author: Bj��rn S��llarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
-- (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
-    // If the image does not have an alpha layer, add one
-    UIImage *image = [self imageWithAlpha];
-    
-    // Build a context that's the same dimensions as the new size
-    CGContextRef context = CGBitmapContextCreate(NULL,
-                                                 image.size.width,
-                                                 image.size.height,
-                                                 CGImageGetBitsPerComponent(image.CGImage),
-                                                 0,
-                                                 CGImageGetColorSpace(image.CGImage),
-                                                 CGImageGetBitmapInfo(image.CGImage));
-
-    // Create a clipping path with rounded corners
-    CGContextBeginPath(context);
-    [self addRoundedRectToPath:CGRectMake(borderSize, borderSize, image.size.width - borderSize * 2, image.size.height - borderSize * 2)
-                       context:context
-                     ovalWidth:cornerSize
-                    ovalHeight:cornerSize];
-    CGContextClosePath(context);
-    CGContextClip(context);
-
-    // Draw the image to the context; the clipping path will make anything outside the rounded rect transparent
-    CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
-    
-    // Create a CGImage from the context
-    CGImageRef clippedImage = CGBitmapContextCreateImage(context);
-    CGContextRelease(context);
-    
-    // Create a UIImage from the CGImage
-    UIImage *roundedImage = [UIImage imageWithCGImage:clippedImage];
-    CGImageRelease(clippedImage);
-    
-    return roundedImage;
-}
-
-#pragma mark -
-#pragma mark Private helper methods
-
-// Adds a rectangular path to the given context and rounds its corners by the given extents
-// Original author: Bj��rn S��llarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
-- (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight {
-    if (ovalWidth == 0 || ovalHeight == 0) {
-        CGContextAddRect(context, rect);
-        return;
-    }
-    CGContextSaveGState(context);
-    CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
-    CGContextScaleCTM(context, ovalWidth, ovalHeight);
-    CGFloat fw = CGRectGetWidth(rect) / ovalWidth;
-    CGFloat fh = CGRectGetHeight(rect) / ovalHeight;
-    CGContextMoveToPoint(context, fw, fh/2);
-    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
-    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
-    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
-    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
-    CGContextClosePath(context);
-    CGContextRestoreGState(context);
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Vector.h b/camerademo/camerademo/demo/UIImage/UIImage+Vector.h
deleted file mode 100755
index 9f93d41..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Vector.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-//  UIImage+Vector.h
-//  UIImage+Vector
-//
-//  Created by David Keegan on 8/7/13.
-//  Copyright (c) 2013 David Keegan All rights reserved.
-//
-
-
-/**
- *  @Author(������)         David Keegan
- *
- *  @URL(������)            https://github.com/kgn/UIImage-Vector
- *
- *  @Version(������)        20150620
- *
- *  @Requirements(������������)
- *
- *  @Description(������)    UIImage category for dealing with vector formats like PDF and icon fonts.
- *  @Usage(������) .. 
- */
-
-#import <UIKit/UIKit.h>
-
-@interface UIImage(Vector)
-
-/**
- Create a UIImage from an icon font.
- @param font The icon font.
- @param iconNamed The name of the icon in the font.
- @param tintColor The tint color to use for the icon. Defaults to black.
- @param clipToBounds If YES the image will be clipped to the pixel bounds of the icon.
- @param fontSize The font size to draw the icon at.
- @return The resulting image.
- */
-+ (UIImage *)iconWithFont:(UIFont *)font named:(NSString *)iconNamed
-            withTintColor:(UIColor *)tintColor clipToBounds:(BOOL)clipToBounds forSize:(CGFloat)fontSize;
-
-/**
- Create a UIImage from a PDF icon.
- @param pdfNamed The name of the PDF file in the application's resources directory.
- @param height The height of the resulting image, the width will be based on the aspect ratio of the PDF.
- @return The resulting image.
- */
-+ (UIImage *)imageWithPDFNamed:(NSString *)pdfNamed forHeight:(CGFloat)height;
-
-/**
- Create a UIImage from a PDF icon.
- @param pdfNamed The name of the PDF file in the application's resources directory.
- @param tintColor The tint color to use for the icon. If nil no tint color will be used.
- @param height The height of the resulting image, the width will be based on the aspect ratio of the PDF.
- @return The resulting image.
- */
-+ (UIImage *)imageWithPDFNamed:(NSString *)pdfNamed withTintColor:(UIColor *)tintColor forHeight:(CGFloat)height;
-
-/**
- Create a UIImage from a PDF icon.
- @param pdfFile The path of the PDF file.
- @param tintColor The tint color to use for the icon. If nil no tint color will be used.
- @param maxSize The maximum size the resulting image can be. The image will maintain it's aspect ratio and may not encumpas the full size.
- @return The resulting image.
- */
-+ (UIImage *)imageWithPDFFile:(NSString *)pdfFile withTintColor:(UIColor *)tintColor forSize:(CGSize)size;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+Vector.m b/camerademo/camerademo/demo/UIImage/UIImage+Vector.m
deleted file mode 100755
index e2d4af0..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+Vector.m
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-//  UIImage+Vector.m
-//  UIImage+Vector
-//
-//  Created by David Keegan on 8/7/13.
-//  Copyright (c) 2013 David Keegan All rights reserved.
-//
-
-#import "UIImage+Vector.h"
-#import <CoreText/CoreText.h>
-
-@implementation UIImage(Vector)
-
-+ (NSCache *)cache{
-    static NSCache *cache = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        cache = [[NSCache alloc] init];
-    });
-    return cache;
-}
-
-+ (UIImage *)iconWithFont:(UIFont *)font named:(NSString *)iconNamed withTintColor:(UIColor *)tintColor clipToBounds:(BOOL)clipToBounds forSize:(CGFloat)fontSize{
-    NSString *identifier = [NSString stringWithFormat:@"%@%@%@%@%d%f", NSStringFromSelector(_cmd), font.fontName, tintColor, iconNamed, clipToBounds, fontSize];
-    UIImage *image = [[self cache] objectForKey:identifier];
-    if(image == nil){
-        NSMutableAttributedString *ligature = [[NSMutableAttributedString alloc] initWithString:iconNamed];
-        [ligature setAttributes:@{(NSString *)kCTLigatureAttributeName: @(2),
-                                  (NSString *)kCTFontAttributeName: font}
-                          range:NSMakeRange(0, [ligature length])];
-
-        CGSize imageSize = [ligature size];
-        imageSize.width = ceil(imageSize.width);
-        imageSize.height = ceil(imageSize.height);
-        if(!CGSizeEqualToSize(CGSizeZero, imageSize)){
-            UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
-            [ligature drawAtPoint:CGPointZero];
-            image = UIGraphicsGetImageFromCurrentImageContext();
-            UIGraphicsEndImageContext();
-
-            if(tintColor){
-                UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
-                CGContextRef context = UIGraphicsGetCurrentContext();
-                CGContextScaleCTM(context, 1, -1);
-                CGContextTranslateCTM(context, 0, -imageSize.height);
-                CGContextClipToMask(context, (CGRect){.size=imageSize}, [image CGImage]);
-                [tintColor setFill];
-                CGContextFillRect(context, (CGRect){.size=imageSize});
-                image = UIGraphicsGetImageFromCurrentImageContext();
-                UIGraphicsEndImageContext();
-            }
-
-            #pragma clang diagnostic push
-            #pragma clang diagnostic ignored "-Wundeclared-selector"
-            if(clipToBounds && [image respondsToSelector:@selector(imageClippedToPixelBounds)]){
-                image = [image performSelector:@selector(imageClippedToPixelBounds)];
-            }
-            #pragma clang diagnostic pop
-
-            [[self cache] setObject:image forKey:identifier];
-        }
-    }
-    return image;
-}
-
-+ (UIImage *)imageWithPDFNamed:(NSString *)pdfNamed forHeight:(CGFloat)height{
-    return [self imageWithPDFNamed:pdfNamed withTintColor:nil forHeight:height];
-}
-
-+ (UIImage *)imageWithPDFNamed:(NSString *)pdfNamed withTintColor:(UIColor *)tintColor forHeight:(CGFloat)height{
-    NSString *pdfFile = [[NSBundle mainBundle] pathForResource:pdfNamed ofType:@"pdf"];
-    return [self imageWithPDFFile:pdfFile withTintColor:tintColor forSize:CGSizeMake(MAXFLOAT, height)];
-}
-
-+ (UIImage *)imageWithPDFFile:(NSString *)pdfFile withTintColor:(UIColor *)tintColor forSize:(CGSize)size{
-    if(!pdfFile || CGSizeEqualToSize(size, CGSizeZero)){
-        return nil;
-    }
-
-    NSString *identifier = [NSString stringWithFormat:@"%@%@%@%@", NSStringFromSelector(_cmd), pdfFile, tintColor, NSStringFromCGSize(size)];
-    UIImage *image = [[self cache] objectForKey:identifier];
-    if(image){
-        return image;
-    }
-
-    NSURL *url = [NSURL fileURLWithPath:pdfFile];
-    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)url);
-    if(!pdf){
-        return nil;
-    }
-
-    CGPDFPageRef page1 = CGPDFDocumentGetPage(pdf, 1);
-    CGRect mediaRect = CGPDFPageGetBoxRect(page1, kCGPDFCropBox);
-
-    CGSize imageSize = mediaRect.size;
-    if(imageSize.height < size.height && size.height != MAXFLOAT){
-        imageSize.width = round(size.height/imageSize.height*imageSize.width);
-        imageSize.height = size.height;
-    }
-    if(imageSize.width < size.width && size.width != MAXFLOAT){
-        imageSize.height = round(size.width/imageSize.width*imageSize.height);
-        imageSize.width = size.width;
-    }
-
-    if(imageSize.height > size.height){
-        imageSize.width = round(size.height/imageSize.height*imageSize.width);
-        imageSize.height = size.height;
-    }
-    if(imageSize.width > size.width){
-        imageSize.height = round(size.width/imageSize.width*imageSize.height);
-        imageSize.width = size.width;
-    }
-
-    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
-    CGFloat scale = MIN(imageSize.width/mediaRect.size.width, imageSize.height/mediaRect.size.height);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    CGContextScaleCTM(context, 1, -1);
-    CGContextTranslateCTM(context, 0, -imageSize.height);
-    CGContextScaleCTM(context, scale, scale);
-    CGContextDrawPDFPage(context, page1);
-    CGPDFDocumentRelease(pdf);
-    image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-
-    if(tintColor){
-        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
-        CGContextRef context = UIGraphicsGetCurrentContext();
-        CGContextScaleCTM(context, 1, -1);
-        CGContextTranslateCTM(context, 0, -imageSize.height);
-        CGContextClipToMask(context, (CGRect){.size=imageSize}, [image CGImage]);
-        [tintColor setFill];
-        CGContextFillRect(context, (CGRect){.size=imageSize});
-        image = UIGraphicsGetImageFromCurrentImageContext();
-        UIGraphicsEndImageContext();
-    }
-
-    return image;
-}
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.h b/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.h
deleted file mode 100755
index 324d814..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#import <UIKit/UIKit.h>
-
-/**
-        UIImage (animatedGIF)
-        
-    This category adds class methods to `UIImage` to create an animated `UIImage` from an animated GIF.
-*/
-@interface UIImage (animatedGIF)
-
-/*
-        UIImage *animation = [UIImage animatedImageWithAnimatedGIFData:theData];
-    
-    I interpret `theData` as a GIF.  I create an animated `UIImage` using the source images in the GIF.
-    
-    The GIF stores a separate duration for each frame, in units of centiseconds (hundredths of a second).  However, a `UIImage` only has a single, total `duration` property, which is a floating-point number.
-    
-    To handle this mismatch, I add each source image (from the GIF) to `animation` a varying number of times to match the ratios between the frame durations in the GIF.
-    
-    For example, suppose the GIF contains three frames.  Frame 0 has duration 3.  Frame 1 has duration 9.  Frame 2 has duration 15.  I divide each duration by the greatest common denominator of all the durations, which is 3, and add each frame the resulting number of times.  Thus `animation` will contain frame 0 3/3 = 1 time, then frame 1 9/3 = 3 times, then frame 2 15/3 = 5 times.  I set `animation.duration` to (3+9+15)/100 = 0.27 seconds.
-*/
-+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)theData;
-
-/*
-        UIImage *image = [UIImage animatedImageWithAnimatedGIFURL:theURL];
-    
-    I interpret the contents of `theURL` as a GIF.  I create an animated `UIImage` using the source images in the GIF.
-    
-    I operate exactly like `+[UIImage animatedImageWithAnimatedGIFData:]`, except that I read the data from `theURL`.  If `theURL` is not a `file:` URL, you probably want to call me on a background thread or GCD queue to avoid blocking the main thread.
-*/
-+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)theURL;
-
-@end
diff --git a/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.m b/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.m
deleted file mode 100755
index f6bdf5f..0000000
--- a/camerademo/camerademo/demo/UIImage/UIImage+animatedGIF.m
+++ /dev/null
@@ -1,114 +0,0 @@
-#import "UIImage+animatedGIF.h"
-#import <ImageIO/ImageIO.h>
-
-#if __has_feature(objc_arc)
-#define toCF (__bridge CFTypeRef)
-#define fromCF (__bridge id)
-#else
-#define toCF (CFTypeRef)
-#define fromCF (id)
-#endif
-
-@implementation UIImage (animatedGIF)
-
-static int delayCentisecondsForImageAtIndex(CGImageSourceRef const source, size_t const i) {
-    int delayCentiseconds = 1;
-    CFDictionaryRef const properties = CGImageSourceCopyPropertiesAtIndex(source, i, NULL);
-    if (properties) {
-        CFDictionaryRef const gifProperties = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
-        CFRelease(properties);
-        if (gifProperties) {
-            CFNumberRef const number = CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime);
-            // Even though the GIF stores the delay as an integer number of centiseconds, ImageIO ���helpfully��� converts that to seconds for us.
-            delayCentiseconds = (int)lrint([fromCF number doubleValue] * 100);
-        }
-    }
-    return delayCentiseconds;
-}
-
-static void createImagesAndDelays(CGImageSourceRef source, size_t count, CGImageRef imagesOut[count], int delayCentisecondsOut[count]) {
-    for (size_t i = 0; i < count; ++i) {
-        imagesOut[i] = CGImageSourceCreateImageAtIndex(source, i, NULL);
-        delayCentisecondsOut[i] = delayCentisecondsForImageAtIndex(source, i);
-    }
-}
-
-static int sum(size_t const count, int const *const values) {
-    int theSum = 0;
-    for (size_t i = 0; i < count; ++i) {
-        theSum += values[i];
-    }
-    return theSum;
-}
-
-static int pairGCD(int a, int b) {
-    if (a < b)
-        return pairGCD(b, a);
-    while (true) {
-        int const r = a % b;
-        if (r == 0)
-            return b;
-        a = b;
-        b = r;
-    }
-}
-
-static int vectorGCD(size_t const count, int const *const values) {
-    int gcd = values[0];
-    for (size_t i = 1; i < count; ++i) {
-        // Note that after I process the first few elements of the vector, `gcd` will probably be smaller than any remaining element.  By passing the smaller value as the second argument to `pairGCD`, I avoid making it swap the arguments.
-        gcd = pairGCD(values[i], gcd);
-    }
-    return gcd;
-}
-
-static NSArray *frameArray(size_t const count, CGImageRef const images[count], int const delayCentiseconds[count], int const totalDurationCentiseconds) {
-    int const gcd = vectorGCD(count, delayCentiseconds);
-    size_t const frameCount = totalDurationCentiseconds / gcd;
-    UIImage *frames[frameCount];
-    for (size_t i = 0, f = 0; i < count; ++i) {
-        UIImage *const frame = [UIImage imageWithCGImage:images[i]];
-        for (size_t j = delayCentiseconds[i] / gcd; j > 0; --j) {
-            frames[f++] = frame;
-        }
-    }
-    return [NSArray arrayWithObjects:frames count:frameCount];
-}
-
-static void releaseImages(size_t const count, CGImageRef const images[count]) {
-    for (size_t i = 0; i < count; ++i) {
-        CGImageRelease(images[i]);
-    }
-}
-
-static UIImage *animatedImageWithAnimatedGIFImageSource(CGImageSourceRef const source) {
-    size_t const count = CGImageSourceGetCount(source);
-    CGImageRef images[count];
-    int delayCentiseconds[count]; // in centiseconds
-    createImagesAndDelays(source, count, images, delayCentiseconds);
-    int const totalDurationCentiseconds = sum(count, delayCentiseconds);
-    NSArray *const frames = frameArray(count, images, delayCentiseconds, totalDurationCentiseconds);
-    UIImage *const animation = [UIImage animatedImageWithImages:frames duration:(NSTimeInterval)totalDurationCentiseconds / 100.0];
-    releaseImages(count, images);
-    return animation;
-}
-
-static UIImage *animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceRef source) {
-    if (source) {
-        UIImage *const image = animatedImageWithAnimatedGIFImageSource(source);
-        CFRelease(source);
-        return image;
-    } else {
-        return nil;
-    }
-}
-
-+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)data {
-    return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithData(toCF data, NULL));
-}
-
-+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)url {
-    return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL(toCF url, NULL));
-}
-
-@end

--
Gitblit v1.8.0