diff --git a/.gitmodules b/.gitmodules index 120d2ae8..3c3d57e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ [submodule "Example"] path = Example url = https://github.com/magicismight/react-native-svg-example.git - -[submodule "ios/PerformanceBezier"] - path = ios/PerformanceBezier - url = https://github.com/adamwulf/PerformanceBezier.git diff --git a/ios/PerformanceBezier b/ios/PerformanceBezier deleted file mode 160000 index 0e0ad4b0..00000000 --- a/ios/PerformanceBezier +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0e0ad4b0303ec80c3c32257addfef9ef6e2a2eb7 diff --git a/ios/QuartzBookPack/Bezier/Bezier.h b/ios/QuartzBookPack/Bezier/Bezier.h deleted file mode 100644 index a418bf3a..00000000 --- a/ios/QuartzBookPack/Bezier/Bezier.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - BEZIER PACK - - */ - -#import -#import -#import - -#import "BaseGeometry.h" -#import "BezierUtils.h" -#import "BezierElement.h" -#import "BezierFunctions.h" -#import "UIBezierPath+Elements.h" diff --git a/ios/QuartzBookPack/Bezier/BezierElement.h b/ios/QuartzBookPack/Bezier/BezierElement.h deleted file mode 100644 index 315a156c..00000000 --- a/ios/QuartzBookPack/Bezier/BezierElement.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - - -#import -#import - -// Block for transforming points -typedef CGPoint (^PathBlock)(CGPoint point); - -@interface BezierElement : NSObject - -// Element storage -@property (nonatomic, assign) CGPathElementType elementType; -@property (nonatomic, assign) CGPoint point; -@property (nonatomic, assign) CGPoint controlPoint1; -@property (nonatomic, assign) CGPoint controlPoint2; - -// Instance creation -+ (instancetype) elementWithPathElement: (CGPathElement) element; - -// Applying transformations -- (BezierElement *) elementByApplyingBlock: (PathBlock) block; - -// Adding to path -- (void) addToPath: (UIBezierPath *) path; - -// Readable forms -@property (nonatomic, readonly) NSString *stringValue; -- (void) showTheCode; -@end; diff --git a/ios/QuartzBookPack/Bezier/BezierElement.m b/ios/QuartzBookPack/Bezier/BezierElement.m deleted file mode 100644 index 057a2bea..00000000 --- a/ios/QuartzBookPack/Bezier/BezierElement.m +++ /dev/null @@ -1,163 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - - -#import "Bezier.h" - -#pragma mark - Bezier Element - - -@implementation BezierElement -- (instancetype) init -{ - self = [super init]; - if (self) - { - _elementType = kCGPathElementMoveToPoint; - _point = NULLPOINT; - _controlPoint1 = NULLPOINT; - _controlPoint2 = NULLPOINT; - } - return self; -} - -+ (instancetype) elementWithPathElement: (CGPathElement) element -{ - BezierElement *newElement = [[self alloc] init]; - newElement.elementType = element.type; - - switch (newElement.elementType) - { - case kCGPathElementCloseSubpath: - break; - case kCGPathElementMoveToPoint: - case kCGPathElementAddLineToPoint: - { - newElement.point = element.points[0]; - break; - } - case kCGPathElementAddQuadCurveToPoint: - { - newElement.point = element.points[1]; - newElement.controlPoint1 = element.points[0]; - break; - } - case kCGPathElementAddCurveToPoint: - { - newElement.point = element.points[2]; - newElement.controlPoint1 = element.points[0]; - newElement.controlPoint2 = element.points[1]; - break; - } - default: - break; - } - - return newElement; -} - -- (instancetype) copyWithZone: (NSZone *) zone -{ - BezierElement *theCopy = [[[self class] allocWithZone:zone] init]; - if (theCopy) - { - theCopy.elementType = _elementType; - theCopy.point = _point; - theCopy.controlPoint1 = _controlPoint1; - theCopy.controlPoint2 = _controlPoint2; - } - return theCopy; -} - -#pragma mark - Path - -- (BezierElement *) elementByApplyingBlock: (PathBlock) block -{ - BezierElement *output = [self copy]; - if (!block) - return output; - - if (!POINT_IS_NULL(output.point)) - output.point = block(output.point); - if (!POINT_IS_NULL(output.controlPoint1)) - output.controlPoint1 = block(output.controlPoint1); - if (!POINT_IS_NULL(output.controlPoint2)) - output.controlPoint2 = block(output.controlPoint2); - return output; -} - -- (void) addToPath: (UIBezierPath *) path -{ - switch (self.elementType) - { - case kCGPathElementCloseSubpath: - [path closePath]; - break; - case kCGPathElementMoveToPoint: - [path moveToPoint:self.point]; - break; - case kCGPathElementAddLineToPoint: - [path addLineToPoint:self.point]; - break; - case kCGPathElementAddQuadCurveToPoint: - [path addQuadCurveToPoint:self.point controlPoint:self.controlPoint1]; - break; - case kCGPathElementAddCurveToPoint: - [path addCurveToPoint:self.point controlPoint1:self.controlPoint1 controlPoint2:self.controlPoint2]; - break; - default: - break; - } -} - -#pragma mark - Strings - -- (NSString *) stringValue -{ - switch (self.elementType) - { - case kCGPathElementCloseSubpath: - return @"Close Path"; - case kCGPathElementMoveToPoint: - return [NSString stringWithFormat:@"Move to point %@", POINTSTRING(self.point)]; - case kCGPathElementAddLineToPoint: - return [NSString stringWithFormat:@"Add line to point %@", POINTSTRING(self.point)]; - case kCGPathElementAddQuadCurveToPoint: - return [NSString stringWithFormat:@"Add quad curve to point %@ with control point %@", POINTSTRING(self.point), POINTSTRING(self.controlPoint1)]; - case kCGPathElementAddCurveToPoint: - return [NSString stringWithFormat:@"Add curve to point %@ with control points %@ and %@", POINTSTRING(self.point), POINTSTRING(self.controlPoint1), POINTSTRING(self.controlPoint2)]; - } - return nil; -} - -- (void) showTheCode -{ - switch (self.elementType) - { - case kCGPathElementCloseSubpath: - printf(" [path closePath];\n\n"); - break; - case kCGPathElementMoveToPoint: - printf(" [path moveToPoint:CGPointMake(%f, %f)];\n", - self.point.x, self.point.y); - break; - case kCGPathElementAddLineToPoint: - printf(" [path addLineToPoint:CGPointMake(%f, %f)];\n", - self.point.x, self.point.y); - break; - case kCGPathElementAddQuadCurveToPoint: - printf(" [path addQuadCurveToPoint:CGPointMake(%f, %f) controlPoint:CGPointMake(%f, %f)];\n", - self.point.x, self.point.y, self.controlPoint1.x, self.controlPoint1.y); - break; - case kCGPathElementAddCurveToPoint: - printf(" [path addCurveToPoint:CGPointMake(%f, %f) controlPoint1:CGPointMake(%f, %f) controlPoint2:CGPointMake(%f, %f)];\n", - self.point.x, self.point.y, self.controlPoint1.x, self.controlPoint1.y, self.controlPoint2.x, self.controlPoint2.y); - break; - default: - break; - } -} -@end - diff --git a/ios/QuartzBookPack/Bezier/BezierFunctions.h b/ios/QuartzBookPack/Bezier/BezierFunctions.h deleted file mode 100644 index 74053634..00000000 --- a/ios/QuartzBookPack/Bezier/BezierFunctions.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "BezierElement.h" - -#define NUMBER_OF_BEZIER_SAMPLES 6 - -typedef CGFloat (^InterpolationBlock)(CGFloat percent); - -// Return Bezier Value -float CubicBezier(float t, float start, float c1, float c2, float end); -float QuadBezier(float t, float start, float c1, float end); - -// Return Bezier Point -CGPoint CubicBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint c2, CGPoint end); -CGPoint QuadBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint end); - -// Calculate Curve Length -float CubicBezierLength(CGPoint start, CGPoint c1, CGPoint c2, CGPoint end); -float QuadBezierLength(CGPoint start, CGPoint c1, CGPoint end); - -// Element Distance -CGFloat ElementDistanceFromPoint(BezierElement *element, CGPoint point, CGPoint startPoint); - -// Linear Interpolation -CGPoint InterpolateLineSegment(CGPoint p1, CGPoint p2, CGFloat percent, CGPoint *slope); - -// Interpolate along element -CGPoint InterpolatePointFromElement(BezierElement *element, CGPoint point, CGPoint startPoint, CGFloat percent, CGPoint *slope); - -// Ease -CGFloat EaseIn(CGFloat currentTime, int factor); -CGFloat EaseOut(CGFloat currentTime, int factor); -CGFloat EaseInOut(CGFloat currentTime, int factor); diff --git a/ios/QuartzBookPack/Bezier/BezierFunctions.m b/ios/QuartzBookPack/Bezier/BezierFunctions.m deleted file mode 100644 index 6003e404..00000000 --- a/ios/QuartzBookPack/Bezier/BezierFunctions.m +++ /dev/null @@ -1,205 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "Bezier.h" - -#pragma mark - Bezier functions -float CubicBezier(float t, float start, float c1, float c2, float end) -{ - CGFloat t_ = (1.0 - t); - CGFloat tt_ = t_ * t_; - CGFloat ttt_ = t_ * t_ * t_; - CGFloat tt = t * t; - CGFloat ttt = t * t * t; - - return start * ttt_ - + 3.0 * c1 * tt_ * t - + 3.0 * c2 * t_ * tt - + end * ttt; -} - -float QuadBezier(float t, float start, float c1, float end) -{ - CGFloat t_ = (1.0 - t); - CGFloat tt_ = t_ * t_; - CGFloat tt = t * t; - - return start * tt_ - + 2.0 * c1 * t_ * t - + end * tt; -} - -CGPoint CubicBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint c2, CGPoint end) -{ - CGPoint result; - result.x = CubicBezier(t, start.x, c1.x, c2.x, end.x); - result.y = CubicBezier(t, start.y, c1.y, c2.y, end.y); - return result; -} - -CGPoint QuadBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint end) -{ - CGPoint result; - result.x = QuadBezier(t, start.x, c1.x, end.x); - result.y = QuadBezier(t, start.y, c1.y, end.y); - return result; -} - -float CubicBezierLength(CGPoint start, CGPoint c1, CGPoint c2, CGPoint end) -{ - int steps = NUMBER_OF_BEZIER_SAMPLES; - CGPoint current; - CGPoint previous; - float length = 0.0; - - for (int i = 0; i <= steps; i++) - { - float t = (float) i / (float) steps; - current = CubicBezierPoint(t, start, c1, c2, end); - if (i > 0) - length += PointDistanceFromPoint(current, previous); - previous = current; - } - - return length; -} - -float QuadBezierLength(CGPoint start, CGPoint c1, CGPoint end) -{ - int steps = NUMBER_OF_BEZIER_SAMPLES; - CGPoint current; - CGPoint previous; - float length = 0.0; - - for (int i = 0; i <= steps; i++) - { - float t = (float) i / (float) steps; - current = QuadBezierPoint(t, start, c1, end); - if (i > 0) - length += PointDistanceFromPoint(current, previous); - previous = current; - } - - return length; -} - - -#pragma mark - Point Percents -#define USE_CURVE_TWEAK 0 -#if USE_CURVE_TWEAK -#define CURVETWEAK 0.8 -#else -#define CURVETWEAK 1.0 -#endif - -CGFloat ElementDistanceFromPoint(BezierElement *element, CGPoint point, CGPoint startPoint) -{ - CGFloat distance = 0.0f; - switch (element.elementType) - { - case kCGPathElementMoveToPoint: - return 0.0f; - case kCGPathElementCloseSubpath: - return PointDistanceFromPoint(point, startPoint); - case kCGPathElementAddLineToPoint: - return PointDistanceFromPoint(point, element.point); - case kCGPathElementAddCurveToPoint: - return CubicBezierLength(point, element.controlPoint1, element.controlPoint2, element.point) * CURVETWEAK; - case kCGPathElementAddQuadCurveToPoint: - return QuadBezierLength(point, element.controlPoint1, element.point) * CURVETWEAK; - } - - return distance; -} - -// Centralize for both close subpath and add line to point -CGPoint InterpolateLineSegment(CGPoint p1, CGPoint p2, CGFloat percent, CGPoint *slope) -{ - CGFloat dx = p2.x - p1.x; - CGFloat dy = p2.y - p1.y; - - if (slope) - *slope = CGPointMake(dx, dy); - - CGFloat px = p1.x + dx * percent; - CGFloat py = p1.y + dy * percent; - - return CGPointMake(px, py); -} - -// Interpolate along element -CGPoint InterpolatePointFromElement(BezierElement *element, CGPoint point, CGPoint startPoint, CGFloat percent, CGPoint *slope) -{ - switch (element.elementType) - { - case kCGPathElementMoveToPoint: - { - // No distance - if (slope) - *slope = CGPointMake(INFINITY, INFINITY); - return point; - } - - case kCGPathElementCloseSubpath: - { - // from self.point to firstPoint - CGPoint p = InterpolateLineSegment(point, startPoint, percent, slope); - return p; - } - - case kCGPathElementAddLineToPoint: - { - // from point to self.point - CGPoint p = InterpolateLineSegment(point, element.point, percent, slope); - return p; - } - - case kCGPathElementAddQuadCurveToPoint: - { - // from point to self.point - CGPoint p = QuadBezierPoint(percent, point, element.controlPoint1, element.point); - CGFloat dx = p.x - QuadBezier(percent * 0.9, point.x, element.controlPoint1.x, element.point.x); - CGFloat dy = p.y - QuadBezier(percent * 0.9, point.y, element.controlPoint1.y, element.point.y); - if (slope) - *slope = CGPointMake(dx, dy); - return p; - } - - case kCGPathElementAddCurveToPoint: - { - // from point to self.point - CGPoint p = CubicBezierPoint(percent, point, element.controlPoint1, element.controlPoint2, element.point); - CGFloat dx = p.x - CubicBezier(percent * 0.9, point.x, element.controlPoint1.x, element.controlPoint2.x, element.point.x); - CGFloat dy = p.y - CubicBezier(percent * 0.9, point.y, element.controlPoint1.y, element.controlPoint2.y, element.point.y); - if (slope) - *slope = CGPointMake(dx, dy); - return p; - } - } - - return NULLPOINT; -} - -CGFloat EaseIn(CGFloat currentTime, int factor) -{ - return powf(currentTime, factor); -} - -CGFloat EaseOut(CGFloat currentTime, int factor) -{ - return 1 - powf((1 - currentTime), factor); -} - -CGFloat EaseInOut(CGFloat currentTime, int factor) -{ - currentTime = currentTime * 2.0; - if (currentTime < 1) - return (0.5 * pow(currentTime, factor)); - currentTime -= 2.0; - if (factor % 2) - return 0.5 * (pow(currentTime, factor) + 2.0); - return 0.5 * (2.0 - pow(currentTime, factor)); -} \ No newline at end of file diff --git a/ios/QuartzBookPack/Bezier/BezierUtils.h b/ios/QuartzBookPack/Bezier/BezierUtils.h deleted file mode 100644 index 84c1794a..00000000 --- a/ios/QuartzBookPack/Bezier/BezierUtils.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "BaseGeometry.h" - -CGRect PathBoundingBox(UIBezierPath *path); -CGRect PathBoundingBoxWithLineWidth(UIBezierPath *path); -CGPoint PathBoundingCenter(UIBezierPath *path); -CGPoint PathCenter(UIBezierPath *path); - -// Transformations -void ApplyCenteredPathTransform(UIBezierPath *path, CGAffineTransform transform); -UIBezierPath *PathByApplyingTransform(UIBezierPath *path, CGAffineTransform transform); - -// Utility -void RotatePath(UIBezierPath *path, CGFloat theta); -void ScalePath(UIBezierPath *path, CGFloat sx, CGFloat sy); -void OffsetPath(UIBezierPath *path, CGSize offset); -void MovePathToPoint(UIBezierPath *path, CGPoint point); -void MovePathCenterToPoint(UIBezierPath *path, CGPoint point); -void MirrorPathHorizontally(UIBezierPath *path); -void MirrorPathVertically(UIBezierPath *path); - -// Fitting -void FitPathToRect(UIBezierPath *path, CGRect rect); -void AdjustPathToRect(UIBezierPath *path, CGRect destRect); - -// Path Attributes -void CopyBezierState(UIBezierPath *source, UIBezierPath *destination); -void CopyBezierDashes(UIBezierPath *source, UIBezierPath *destination); -void AddDashesToPath(UIBezierPath *path); - -// String to Path -UIBezierPath *BezierPathFromString(NSString *string, UIFont *font); -UIBezierPath *BezierPathFromStringWithFontFace(NSString *string, NSString *fontFace); - -// Draw Text in Path -void DrawAttributedStringInBezierPath(UIBezierPath *path, NSAttributedString *attributedString); -void DrawAttributedStringInBezierSubpaths(UIBezierPath *path, NSAttributedString *attributedString); - -// N-Gons -UIBezierPath *BezierPolygon(NSUInteger numberOfSides); -UIBezierPath *BezierInflectedShape(NSUInteger numberOfInflections, CGFloat percentInflection); -UIBezierPath *BezierStarShape(NSUInteger numberOfInflections, CGFloat percentInflection); - -// Misc -void ClipToRect(CGRect rect); -void FillRect(CGRect rect, UIColor *color); -void ShowPathProgression(UIBezierPath *path, CGFloat maxPercent); - -// Effects -void SetShadow(UIColor *color, CGSize size, CGFloat blur); -void DrawShadow(UIBezierPath *path, UIColor *color, CGSize size, CGFloat blur); -void DrawInnerShadow(UIBezierPath *path, UIColor *color, CGSize size, CGFloat blur); -void EmbossPath(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat blur); -void BevelPath(UIBezierPath *p, UIColor *color, CGFloat r, CGFloat theta); -void InnerBevel(UIBezierPath *p, UIColor *color, CGFloat r, CGFloat theta); -void ExtrudePath(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat angle); - -@interface UIBezierPath (HandyUtilities) -@property (nonatomic, readonly) CGPoint center; -@property (nonatomic, readonly) CGRect computedBounds; -@property (nonatomic, readonly) CGRect computedBoundsWithLineWidth; - -// Stroke/Fill -- (void) stroke: (CGFloat) width; -- (void) stroke: (CGFloat) width color: (UIColor *) color; -- (void) strokeInside: (CGFloat) width; -- (void) strokeInside: (CGFloat) width color: (UIColor *) color; -- (void) fill: (UIColor *) fillColor; -- (void) fill: (UIColor *) fillColor withMode: (CGBlendMode) blendMode; -- (void) fillWithNoise: (UIColor *) fillColor; -- (void) addDashes; -- (void) addDashes: (NSArray *) pattern; -- (void) applyPathPropertiesToContext; - -// Clipping -- (void) clipToPath; // I hate addClip -- (void) clipToStroke: (NSUInteger) width; - -// Util -- (UIBezierPath *) safeCopy; -@end diff --git a/ios/QuartzBookPack/Bezier/BezierUtils.m b/ios/QuartzBookPack/Bezier/BezierUtils.m deleted file mode 100644 index 018a1c12..00000000 --- a/ios/QuartzBookPack/Bezier/BezierUtils.m +++ /dev/null @@ -1,709 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "BezierUtils.h" -#import "Utility.h" - -#pragma mark - Bounds -CGRect PathBoundingBox(UIBezierPath *path) -{ - return CGPathGetPathBoundingBox(path.CGPath); -} - -CGRect PathBoundingBoxWithLineWidth(UIBezierPath *path) -{ - CGRect bounds = PathBoundingBox(path); - return CGRectInset(bounds, -path.lineWidth / 2.0f, -path.lineWidth / 2.0f); -} - -CGPoint PathBoundingCenter(UIBezierPath *path) -{ - return RectGetCenter(PathBoundingBox(path)); -} - -CGPoint PathCenter(UIBezierPath *path) -{ - return RectGetCenter(path.bounds); -} - -#pragma mark - Misc -void ClipToRect(CGRect rect) -{ - [[UIBezierPath bezierPathWithRect:rect] addClip]; -} - -void FillRect(CGRect rect, UIColor *color) -{ - [[UIBezierPath bezierPathWithRect:rect] fill:color]; -} - -void ShowPathProgression(UIBezierPath *path, CGFloat maxPercent) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGFloat maximumPercent = fmax(fmin(maxPercent, 1.0f), 0.0f); - PushDraw(^{ - CGFloat distance = path.pathLength; - int samples = distance / 6; - float dLevel = 0.75 / (CGFloat) samples; - - UIBezierPath *marker; - for (int i = 0; i <= samples * maximumPercent; i++) - { - CGFloat percent = (CGFloat) i / (CGFloat) samples; - CGPoint point = [path pointAtPercent:percent withSlope:NULL]; - UIColor *color = [UIColor colorWithWhite:i * dLevel alpha:1]; - - CGRect r = RectAroundCenter(point, CGSizeMake(2, 2)); - marker = [UIBezierPath bezierPathWithOvalInRect:r]; - [marker fill:color]; - } - }); -} - -#pragma mark - Transform -void ApplyCenteredPathTransform(UIBezierPath *path, CGAffineTransform transform) -{ - CGPoint center = PathBoundingCenter(path); - CGAffineTransform t = CGAffineTransformIdentity; - t = CGAffineTransformTranslate(t, center.x, center.y); - t = CGAffineTransformConcat(transform, t); - t = CGAffineTransformTranslate(t, -center.x, -center.y); - [path applyTransform:t]; -} - -UIBezierPath *PathByApplyingTransform(UIBezierPath *path, CGAffineTransform transform) -{ - UIBezierPath *copy = [path copy]; - ApplyCenteredPathTransform(copy, transform); - return copy; -} - -void RotatePath(UIBezierPath *path, CGFloat theta) -{ - CGAffineTransform t = CGAffineTransformMakeRotation(theta); - ApplyCenteredPathTransform(path, t); -} - -void ScalePath(UIBezierPath *path, CGFloat sx, CGFloat sy) -{ - CGAffineTransform t = CGAffineTransformMakeScale(sx, sy); - ApplyCenteredPathTransform(path, t); -} - -void OffsetPath(UIBezierPath *path, CGSize offset) -{ - CGAffineTransform t = CGAffineTransformMakeTranslation(offset.width, offset.height); - ApplyCenteredPathTransform(path, t); -} - -void MovePathToPoint(UIBezierPath *path, CGPoint destPoint) -{ - CGRect bounds = PathBoundingBox(path); - CGPoint p1 = bounds.origin; - CGPoint p2 = destPoint; - CGSize vector = CGSizeMake(p2.x - p1.x, p2.y - p1.y); - OffsetPath(path, vector); -} - -void MovePathCenterToPoint(UIBezierPath *path, CGPoint destPoint) -{ - CGRect bounds = PathBoundingBox(path); - CGPoint p1 = bounds.origin; - CGPoint p2 = destPoint; - CGSize vector = CGSizeMake(p2.x - p1.x, p2.y - p1.y); - vector.width -= bounds.size.width / 2.0f; - vector.height -= bounds.size.height / 2.0f; - OffsetPath(path, vector); -} - -void MirrorPathHorizontally(UIBezierPath *path) -{ - CGAffineTransform t = CGAffineTransformMakeScale(-1, 1); - ApplyCenteredPathTransform(path, t); -} - -void MirrorPathVertically(UIBezierPath *path) -{ - CGAffineTransform t = CGAffineTransformMakeScale(1, -1); - ApplyCenteredPathTransform(path, t); -} - -void FitPathToRect(UIBezierPath *path, CGRect destRect) -{ - CGRect bounds = PathBoundingBox(path); - CGRect fitRect = RectByFittingRect(bounds, destRect); - CGFloat scale = AspectScaleFit(bounds.size, destRect); - - CGPoint newCenter = RectGetCenter(fitRect); - MovePathCenterToPoint(path, newCenter); - ScalePath(path, scale, scale); -} - -void AdjustPathToRect(UIBezierPath *path, CGRect destRect) -{ - CGRect bounds = PathBoundingBox(path); - CGFloat scaleX = destRect.size.width / bounds.size.width; - CGFloat scaleY = destRect.size.height / bounds.size.height; - - CGPoint newCenter = RectGetCenter(destRect); - MovePathCenterToPoint(path, newCenter); - ScalePath(path, scaleX, scaleY); -} - -#pragma mark - Path Attributes -void AddDashesToPath(UIBezierPath *path) -{ - CGFloat dashes[] = {6, 2}; - [path setLineDash:dashes count:2 phase:0]; -} - -void CopyBezierDashes(UIBezierPath *source, UIBezierPath *destination) -{ - NSInteger count; - [source getLineDash:NULL count:&count phase:NULL]; - - CGFloat phase; - CGFloat *pattern = malloc(count * sizeof(CGFloat)); - [source getLineDash:pattern count:&count phase:&phase]; - [destination setLineDash:pattern count:count phase:phase]; - free(pattern); -} - -void CopyBezierState(UIBezierPath *source, UIBezierPath *destination) -{ - destination.lineWidth = source.lineWidth; - destination.lineCapStyle = source.lineCapStyle; - destination.lineJoinStyle = source.lineJoinStyle; - destination.miterLimit = source.miterLimit; - destination.flatness = source.flatness; - destination.usesEvenOddFillRule = source.usesEvenOddFillRule; - CopyBezierDashes(source, destination); -} - -#pragma mark - Text -UIBezierPath *BezierPathFromString(NSString *string, UIFont *font) -{ - // Initialize path - UIBezierPath *path = [UIBezierPath bezierPath]; - if (!string.length) return path; - - // Create font ref - CTFontRef fontRef = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL); - if (fontRef == NULL) - { - NSLog(@"Error retrieving CTFontRef from UIFont"); - return nil; - } - - // Create glyphs - CGGlyph *glyphs = malloc(sizeof(CGGlyph) * string.length); - const unichar *chars = (const unichar *)[string cStringUsingEncoding:NSUnicodeStringEncoding]; - BOOL success = CTFontGetGlyphsForCharacters(fontRef, chars, glyphs, string.length); - if (!success) - { - NSLog(@"Error retrieving string glyphs"); - CFRelease(fontRef); - free(glyphs); - return nil; - } - - // Draw each char into path - for (int i = 0; i < string.length; i++) - { - CGGlyph glyph = glyphs[i]; - CGPathRef pathRef = CTFontCreatePathForGlyph(fontRef, glyph, NULL); - [path appendPath:[UIBezierPath bezierPathWithCGPath:pathRef]]; - CGPathRelease(pathRef); - CGSize size = [[string substringWithRange:NSMakeRange(i, 1)] sizeWithAttributes:@{NSFontAttributeName:font}]; - OffsetPath(path, CGSizeMake(-size.width, 0)); - } - - // Clean up - free(glyphs); - CFRelease(fontRef); - - // Math - MirrorPathVertically(path); - return path; -} - -UIBezierPath *BezierPathFromStringWithFontFace(NSString *string, NSString *fontFace) -{ - UIFont *font = [UIFont fontWithName:fontFace size:16]; - if (!font) - font = [UIFont systemFontOfSize:16]; - return BezierPathFromString(string, font); -} - -// Listing 8-1 -void MirrorPathVerticallyInContext(UIBezierPath *path) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGSize size = GetUIKitContextSize(); - CGRect contextRect = SizeMakeRect(size); - CGPoint center = RectGetCenter(contextRect); - - CGAffineTransform t = CGAffineTransformIdentity; - t = CGAffineTransformTranslate(t, center.x, center.y); - t = CGAffineTransformScale(t, 1, -1); - t = CGAffineTransformTranslate(t, -center.x, -center.y); - [path applyTransform:t]; -} - -void DrawAttributedStringIntoSubpath(UIBezierPath *path, NSAttributedString *attributedString, NSAttributedString **remainder) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - UIBezierPath *copy = [path safeCopy]; - MirrorPathVerticallyInContext(copy); - - CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) attributedString); - CTFrameRef theFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributedString.length), copy.CGPath, NULL); - - if (remainder) - { - CFRange range = CTFrameGetVisibleStringRange(theFrame); - NSInteger startLocation = range.location + range.length; - NSInteger extent = attributedString.length - startLocation; - NSAttributedString *substring = [attributedString attributedSubstringFromRange:NSMakeRange(startLocation, extent)]; - *remainder = substring; - } - - PushDraw(^{ - CGContextSetTextMatrix(context, CGAffineTransformIdentity); - FlipContextVertically(GetUIKitContextSize()); - CTFrameDraw(theFrame, UIGraphicsGetCurrentContext()); - }); - - CFRelease(theFrame); - CFRelease(framesetter); -} - -void DrawAttributedStringInBezierPath(UIBezierPath *path, NSAttributedString *attributedString) -{ - DrawAttributedStringIntoSubpath(path, attributedString, nil); -} - -void DrawAttributedStringInBezierSubpaths(UIBezierPath *path, NSAttributedString *attributedString) -{ - NSAttributedString *string; - NSAttributedString *remainder = attributedString; - - for (UIBezierPath *subpath in path.subpaths) - { - string = remainder; - DrawAttributedStringIntoSubpath(subpath, string, &remainder); - if (remainder.length == 0) return; - } -} - -#pragma mark - Polygon Fun -UIBezierPath *BezierPolygon(NSUInteger numberOfSides) -{ - if (numberOfSides < 3) - { - NSLog(@"Error: Please supply at least 3 sides"); - return nil; - } - - CGRect destinationRect = CGRectMake(0, 0, 1, 1); - - UIBezierPath *path = [UIBezierPath bezierPath]; - CGPoint center = RectGetCenter(destinationRect); - CGFloat r = 0.5f; // radius - - BOOL firstPoint = YES; - for (int i = 0; i < (numberOfSides - 1); i++) - { - CGFloat theta = M_PI + i * TWO_PI / numberOfSides; - CGFloat dTheta = TWO_PI / numberOfSides; - - CGPoint p; - if (firstPoint) - { - p.x = center.x + r * sin(theta); - p.y = center.y + r * cos(theta); - [path moveToPoint:p]; - firstPoint = NO; - } - - p.x = center.x + r * sin(theta + dTheta); - p.y = center.y + r * cos(theta + dTheta); - [path addLineToPoint:p]; - } - - [path closePath]; - - return path; -} - -UIBezierPath *BezierInflectedShape(NSUInteger numberOfInflections, CGFloat percentInflection) -{ - if (numberOfInflections < 3) - { - NSLog(@"Error: Please supply at least 3 inflections"); - return nil; - } - - UIBezierPath *path = [UIBezierPath bezierPath]; - CGRect destinationRect = CGRectMake(0, 0, 1, 1); - CGPoint center = RectGetCenter(destinationRect); - CGFloat r = 0.5; - CGFloat rr = r * (1.0 + percentInflection); - - BOOL firstPoint = YES; - for (int i = 0; i < numberOfInflections; i++) - { - CGFloat theta = i * TWO_PI / numberOfInflections; - CGFloat dTheta = TWO_PI / numberOfInflections; - - if (firstPoint) - { - CGFloat xa = center.x + r * sin(theta); - CGFloat ya = center.y + r * cos(theta); - CGPoint pa = CGPointMake(xa, ya); - [path moveToPoint:pa]; - firstPoint = NO; - } - - CGFloat cp1x = center.x + rr * sin(theta + dTheta / 3); - CGFloat cp1y = center.y + rr * cos(theta + dTheta / 3); - CGPoint cp1 = CGPointMake(cp1x, cp1y); - - CGFloat cp2x = center.x + rr * sin(theta + 2 * dTheta / 3); - CGFloat cp2y = center.y + rr * cos(theta + 2 * dTheta / 3); - CGPoint cp2 = CGPointMake(cp2x, cp2y); - - CGFloat xb = center.x + r * sin(theta + dTheta); - CGFloat yb = center.y + r * cos(theta + dTheta); - CGPoint pb = CGPointMake(xb, yb); - - [path addCurveToPoint:pb controlPoint1:cp1 controlPoint2:cp2]; - } - - [path closePath]; - - return path; -} - -UIBezierPath *BezierStarShape(NSUInteger numberOfInflections, CGFloat percentInflection) -{ - if (numberOfInflections < 3) - { - NSLog(@"Error: Please supply at least 3 inflections"); - return nil; - } - - UIBezierPath *path = [UIBezierPath bezierPath]; - CGRect destinationRect = CGRectMake(0, 0, 1, 1); - CGPoint center = RectGetCenter(destinationRect); - CGFloat r = 0.5; - CGFloat rr = r * (1.0 + percentInflection); - - BOOL firstPoint = YES; - for (int i = 0; i < numberOfInflections; i++) - { - CGFloat theta = i * TWO_PI / numberOfInflections; - CGFloat dTheta = TWO_PI / numberOfInflections; - - if (firstPoint) - { - CGFloat xa = center.x + r * sin(theta); - CGFloat ya = center.y + r * cos(theta); - CGPoint pa = CGPointMake(xa, ya); - [path moveToPoint:pa]; - firstPoint = NO; - } - - CGFloat cp1x = center.x + rr * sin(theta + dTheta / 2); - CGFloat cp1y = center.y + rr * cos(theta + dTheta / 2); - CGPoint cp1 = CGPointMake(cp1x, cp1y); - - CGFloat xb = center.x + r * sin(theta + dTheta); - CGFloat yb = center.y + r * cos(theta + dTheta); - CGPoint pb = CGPointMake(xb, yb); - - [path addLineToPoint:cp1]; - [path addLineToPoint:pb]; - } - - [path closePath]; - - return path; -} - -#pragma mark - Shadows - -// Establish context shadow state -void SetShadow(UIColor *color, CGSize size, CGFloat blur) -{ - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - if (color) - CGContextSetShadowWithColor(context, size, blur, color.CGColor); - else - CGContextSetShadow(context, size, blur); -} - -// Draw *only* the shadow -void DrawShadow(UIBezierPath *path, UIColor *color, CGSize size, CGFloat blur) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - // Build shadow - PushDraw(^{ - SetShadow(color, CGSizeMake(size.width, size.height), blur); - [path.inverse addClip]; - [path fill:color]; - }); -} - -// Draw shadow inside shape -void DrawInnerShadow(UIBezierPath *path, UIColor *color, CGSize size, CGFloat blur) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - // Build shadow - PushDraw(^{ - SetShadow(color, CGSizeMake(size.width, size.height), blur); - [path addClip]; - [path.inverse fill:color]; - }); -} - -#pragma mark - Photoshop Style Effects -UIColor *ContrastColor(UIColor *color) -{ - if (CGColorSpaceGetNumberOfComponents(CGColorGetColorSpace(color.CGColor)) == 3) - { - CGFloat r, g, b, a; - [color getRed:&r green:&g blue:&b alpha:&a]; - CGFloat luminance = r * 0.2126f + g * 0.7152f + b * 0.0722f; - return (luminance > 0.5f) ? [UIColor blackColor] : [UIColor whiteColor]; - } - - CGFloat w, a; - [color getWhite:&w alpha:&a]; - return (w > 0.5f) ? [UIColor blackColor] : [UIColor whiteColor]; -} - -// Create 3d embossed effect -// Typically call with black color at 0.5 -void EmbossPath(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat blur) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - - UIColor *contrast = ContrastColor(color); - DrawInnerShadow(path, contrast, CGSizeMake(-radius, radius), blur); - DrawInnerShadow(path, color, CGSizeMake(radius, -radius), blur); -} - -// Half an emboss -void InnerBevel(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat theta) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGFloat x = radius * sin(theta); - CGFloat y = radius * cos(theta); - - UIColor *shadowColor = [color colorWithAlphaComponent:0.5f]; - DrawInnerShadow(path, shadowColor, CGSizeMake(-x, y), 2); -} - -// I don't love this -void ExtrudePath(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat theta) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - CGFloat x = radius * sin(theta); - CGFloat y = radius * cos(theta); - DrawShadow(path, color, CGSizeMake(x, y), 0); -} - -// Typically call with black color at 0.5 -void BevelPath(UIBezierPath *path, UIColor *color, CGFloat radius, CGFloat theta) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGFloat x = radius * sin(theta); - CGFloat y = radius * cos(theta); - DrawInnerShadow(path, color, CGSizeMake(-x, y), 2); - DrawShadow(path, color, CGSizeMake(x / 2 , -y / 2), 0); -} - -@implementation UIBezierPath (HandyUtilities) -#pragma mark - Bounds -- (CGPoint) center -{ - return PathBoundingCenter(self); -} - -- (CGRect) computedBounds -{ - return PathBoundingBox(self); -} - -- (CGRect) computedBoundsWithLineWidth -{ - return PathBoundingBoxWithLineWidth(self); -} - -#pragma mark - Stroking and Filling - -- (void) addDashes -{ - AddDashesToPath(self); -} - -- (void) addDashes: (NSArray *) pattern -{ - if (!pattern.count) return; - CGFloat *dashes = malloc(pattern.count * sizeof(CGFloat)); - for (int i = 0; i < pattern.count; i++) - dashes[i] = [pattern[i] floatValue]; - [self setLineDash:dashes count:pattern.count phase:0]; - free(dashes); -} - -- (void) applyPathPropertiesToContext -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGContextSetLineWidth(context, self.lineWidth); - CGContextSetLineCap(context, self.lineCapStyle); - CGContextSetLineJoin(context, self.lineJoinStyle); - CGContextSetMiterLimit(context, self.miterLimit); - CGContextSetFlatness(context, self.flatness); - - NSInteger count; - [self getLineDash:NULL count:&count phase:NULL]; - - CGFloat phase; - CGFloat *pattern = malloc(count * sizeof(CGFloat)); - [self getLineDash:pattern count:&count phase:&phase]; - CGContextSetLineDash(context, phase, pattern, count); - free(pattern); -} - -- (void) stroke: (CGFloat) width color: (UIColor *) color -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - PushDraw(^{ - if (color) [color setStroke]; - CGFloat holdWidth = self.lineWidth; - if (width > 0) - self.lineWidth = width; - [self stroke]; - self.lineWidth = holdWidth; - }); -} - -- (void) stroke: (CGFloat) width -{ - [self stroke:width color:nil]; -} - -- (void) strokeInside: (CGFloat) width color: (UIColor *) color -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - PushDraw(^{ - [self addClip]; - [self stroke:width * 2 color:color]; - }); -} - -- (void) strokeInside: (CGFloat) width -{ - [self strokeInside:width color:nil]; -} - -- (void) fill: (UIColor *) fillColor -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - PushDraw(^{ - if (fillColor) - [fillColor set]; - [self fill]; - }); -} - -- (void) fill: (UIColor *) fillColor withMode: (CGBlendMode) blendMode -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - PushDraw(^{ - CGContextSetBlendMode(context, blendMode); - [self fill:fillColor]; - }); -} - -- (void) fillWithNoise: (UIColor *) fillColor -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - [self fill:fillColor]; - [self fill:[NoiseColor() colorWithAlphaComponent:0.05f] withMode:kCGBlendModeScreen]; -} - -#pragma mark - Clippage -- (void) clipToPath -{ - [self addClip]; -} - -- (void) clipToStroke:(NSUInteger)width -{ - CGPathRef pathRef = CGPathCreateCopyByStrokingPath(self.CGPath, NULL, width, kCGLineCapButt, kCGLineJoinMiter, 4); - UIBezierPath *clipPath = [UIBezierPath bezierPathWithCGPath:pathRef]; - CGPathRelease(pathRef); - [clipPath addClip]; -} - -#pragma mark - Misc - -- (UIBezierPath *) safeCopy -{ - UIBezierPath *p = [UIBezierPath bezierPath]; - [p appendPath:self]; - CopyBezierState(self, p); - return p; -} -@end diff --git a/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.h b/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.h deleted file mode 100644 index d70a7917..00000000 --- a/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "Bezier.h" - -// Construct path -UIBezierPath *BezierPathWithElements(NSArray *elements); -UIBezierPath *BezierPathWithPoints(NSArray *points); -UIBezierPath *InterpolatedPath(UIBezierPath *path); - -// Partial paths -UIBezierPath *CroppedPath(UIBezierPath *path, CGFloat percent); -UIBezierPath *PathFromPercentToPercent(UIBezierPath *path, CGFloat startPercent, CGFloat endPercent); - -/* - - UIBezierPath - Elements Category - - */ - -@interface UIBezierPath (Elements) - -@property (nonatomic, readonly) NSArray *elements; -@property (nonatomic, readonly) NSArray *subpaths; - -@property (nonatomic, readonly) NSArray *destinationPoints; -@property (nonatomic, readonly) NSArray *interpolatedPathPoints; - -@property (nonatomic, readonly) NSUInteger count; -- (id)objectAtIndexedSubscript:(NSUInteger)idx; - -@property (nonatomic, readonly) CGPoint center; -@property (nonatomic, readonly) CGRect calculatedBounds; - -@property (nonatomic, readonly) UIBezierPath *reversed; -@property (nonatomic, readonly) UIBezierPath *inverse; -@property (nonatomic, readonly) UIBezierPath *boundedInverse; - -@property (nonatomic, readonly) BOOL subpathIsClosed; -- (BOOL) closeSafely; - -// Measure length -@property (nonatomic, readonly) CGFloat pathLength; -- (CGPoint) pointAtPercent: (CGFloat) percent withSlope: (CGPoint *) slope; - -// String Representations -- (void) showTheCode; -- (NSString *) stringValue; - -// -- Invert path to arbitrary rectangle -- (UIBezierPath *) inverseInRect: (CGRect) rect; -@end \ No newline at end of file diff --git a/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.m b/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.m deleted file mode 100644 index e951931d..00000000 --- a/ios/QuartzBookPack/Bezier/UIBezierPath+Elements.m +++ /dev/null @@ -1,519 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "UIBezierPath+Elements.h" -#import "BaseGeometry.h" - -#pragma mark - Construction - -// Return Bezier path built with the supplied elements -UIBezierPath *BezierPathWithElements(NSArray *elements) -{ - UIBezierPath *path = [UIBezierPath bezierPath]; - for (BezierElement *element in elements) - [element addToPath:path]; - return path; -} - - -UIBezierPath *InterpolatedPath(UIBezierPath *path) -{ - return BezierPathWithPoints(path.interpolatedPathPoints); -} - -#define POINT(_X_) ([(NSValue *)points[_X_] CGPointValue]) - -// Pass array with NSValue'd CGRect points -UIBezierPath *BezierPathWithPoints(NSArray *points) -{ - UIBezierPath *path = [UIBezierPath bezierPath]; - if (!points.count) - return path; - [path moveToPoint:POINT(0)]; - for (int i = 1; i < points.count; i++) - [path addLineToPoint:POINT(i)]; - [path closePath]; - return path; -} - -#pragma mark - Partial Path - -UIBezierPath *CroppedPath(UIBezierPath *path, CGFloat percent) -{ - NSArray *elements = path.elements; - if (elements.count == 0) return path; - - int targetCount = elements.count * percent; - NSArray *targetElements = [elements subarrayWithRange:NSMakeRange(0, targetCount)]; - UIBezierPath *outputPath = BezierPathWithElements(targetElements); - return outputPath; -} - -UIBezierPath *PathFromPercentToPercent(UIBezierPath *path, CGFloat startPercent, CGFloat endPercent) -{ - NSArray *elements = path.elements; - if (elements.count == 0) return path; - - int targetCount = elements.count * endPercent; - NSArray *targetElements = [elements subarrayWithRange:NSMakeRange(0, targetCount)]; - UIBezierPath *outputPath = BezierPathWithElements(targetElements); - return outputPath; -} - -#pragma mark - Bezier Elements Category - - -@implementation UIBezierPath (Elements) - -// Convert one element to BezierElement and save to array -void GetBezierElements(void *info, const CGPathElement *element) -{ - NSMutableArray *bezierElements = (__bridge NSMutableArray *)info; - if (element) - [bezierElements addObject:[BezierElement elementWithPathElement:*element]]; -} - -// Retrieve array of component elements -- (NSArray *) elements -{ - NSMutableArray *elements = [NSMutableArray array]; - CGPathApply(self.CGPath, (__bridge void *)elements, GetBezierElements); - return elements; -} - -#pragma mark - Subpaths -// Subpaths must be well defined -- (NSMutableArray *) subpaths -{ - NSMutableArray *results = [NSMutableArray array]; - UIBezierPath *current = nil; - NSArray *elements = self.elements; - - for (BezierElement *element in elements) - { - if (element.elementType == kCGPathElementCloseSubpath) - { - [current closePath]; - if (current) - [results addObject:current]; - current = nil; - continue; - } - - if (element.elementType == kCGPathElementMoveToPoint) - { - if (current) - [results addObject:current]; - - current = [UIBezierPath bezierPath]; - [current moveToPoint:element.point]; - continue; - } - - if (current) - [element addToPath:current]; - else - { - NSLog(@"Error: cannot add element to nil path: %@", element.stringValue); - continue; - } - } - - if (current) - [results addObject:current]; - - return results; -} - - -// Only collect those points that have destinations -- (NSArray *) destinationPoints -{ - NSMutableArray *array = [NSMutableArray array]; - NSArray *elements = self.elements; - - for (BezierElement *element in elements) - if (!POINT_IS_NULL(element.point)) - [array addObject:[NSValue valueWithCGPoint:element.point]]; - - return array; -} - -// Points and interpolated points -- (NSArray *) interpolatedPathPoints -{ - NSMutableArray *points = [NSMutableArray array]; - BezierElement *current = nil; - int overkill = 3; - for (BezierElement *element in self.elements) - { - switch (element.elementType) - { - case kCGPathElementMoveToPoint: - case kCGPathElementAddLineToPoint: - [points addObject:[NSValue valueWithCGPoint:element.point]]; - current = element; - break; - case kCGPathElementCloseSubpath: - current = nil; - break; - case kCGPathElementAddCurveToPoint: - { - for (int i = 1; i < NUMBER_OF_BEZIER_SAMPLES * overkill; i++) - { - CGFloat percent = (CGFloat) i / (CGFloat) (NUMBER_OF_BEZIER_SAMPLES * overkill); - CGPoint p = CubicBezierPoint(percent, current.point, element.controlPoint1, element.controlPoint2, element.point); - [points addObject:[NSValue valueWithCGPoint:p]]; - } - [points addObject:[NSValue valueWithCGPoint:element.point]]; - current = element; - break; - } - case kCGPathElementAddQuadCurveToPoint: - { - for (int i = 1; i < NUMBER_OF_BEZIER_SAMPLES * overkill; i++) - { - CGFloat percent = (CGFloat) i / (CGFloat) (NUMBER_OF_BEZIER_SAMPLES * overkill); - CGPoint p = QuadBezierPoint(percent, current.point, element.controlPoint1, element.point); - [points addObject:[NSValue valueWithCGPoint:p]]; - } - [points addObject:[NSValue valueWithCGPoint:element.point]]; - current = element; - break; - } - } - } - return points; -} - -#pragma mark - Array Access - -- (NSUInteger) count -{ - return self.elements.count; -} - -- (id)objectAtIndexedSubscript:(NSUInteger)idx -{ - NSArray *elements = self.elements; - if (idx >= elements.count) - return nil; - return elements[idx]; -} - -#pragma mark - Geometry Workaround -- (CGRect) calculatedBounds -{ - // Thank you Ryan Petrich - return CGPathGetPathBoundingBox(self.CGPath); -} - -// Return center of bounds -- (CGPoint) center -{ - return RectGetCenter(self.calculatedBounds); -} - -#pragma mark - Reversal Workaround -- (UIBezierPath *) reverseSubpath: (UIBezierPath *) subpath -{ - NSArray *elements = subpath.elements; - NSArray *reversedElements = [[elements reverseObjectEnumerator] allObjects]; - - UIBezierPath *newPath = [UIBezierPath bezierPath]; - CopyBezierState(self, newPath); - BOOL closesSubpath = NO; - - BezierElement *firstElement; - for (BezierElement *e in elements) - { - if (!POINT_IS_NULL(e.point)) - { - firstElement = e; - break; - } - } - - BezierElement *lastElement; - for (BezierElement *e in reversedElements) - { - if (!POINT_IS_NULL(e.point)) - { - lastElement = e; - break; - } - } - - BezierElement *element = [elements lastObject]; - if (element.elementType == kCGPathElementCloseSubpath) - { - if (firstElement) - [newPath moveToPoint:firstElement.point]; - - if (lastElement) - [newPath addLineToPoint:lastElement.point]; - - closesSubpath = YES; - } - else - { - [newPath moveToPoint:lastElement.point]; - } - - CFIndex i = 0; - for (BezierElement *element in reversedElements) - { - i++; - BezierElement *nextElement = nil; - BezierElement *workElement = [element copy]; - - if (element.elementType == kCGPathElementCloseSubpath) - continue; - - if (element == firstElement) - { - if (closesSubpath) [newPath closePath]; - continue; - } - - if (i < reversedElements.count) - { - nextElement = reversedElements[i]; - if (!POINT_IS_NULL(workElement.controlPoint2)) - { - CGPoint tmp = workElement.controlPoint1; - workElement.controlPoint1 = workElement.controlPoint2; - workElement.controlPoint2 = tmp; - } - workElement.point = nextElement.point; - } - - if (element.elementType == kCGPathElementMoveToPoint) - workElement.elementType = kCGPathElementAddLineToPoint; - - [workElement addToPath:newPath]; - } - - return newPath; - -} - -- (UIBezierPath *) reversed -{ - // [self bezierPathByReversingPath] seriously does not work the - // way you expect. Radars are filed. - - UIBezierPath *reversed = [UIBezierPath bezierPath]; - NSArray *reversedSubpaths = [[self.subpaths reverseObjectEnumerator] allObjects]; - - for (UIBezierPath *subpath in reversedSubpaths) - { - UIBezierPath *p = [self reverseSubpath:subpath]; - if (p) - [reversed appendPath:p]; - } - return reversed; -} - -#pragma mark - Closing -- (BOOL) subpathIsClosed -{ - NSArray *elements = self.elements; - - // A legal closed path must contain 3 elements - // move, add, close - if (elements.count < 3) - return NO; - - BezierElement *element = [elements lastObject]; - return element.elementType == kCGPathElementCloseSubpath; -} - -- (BOOL) closeSafely -{ - NSArray *elements = self.elements; - if (elements.count < 2) - return NO; - - BezierElement *element = [elements lastObject]; - if (element.elementType != kCGPathElementCloseSubpath) - { - [self closePath]; - return YES; - } - - return NO; -} - - -#pragma mark - Show the Code -- (void) showTheCode -{ - - printf("\n- (UIBezierPath *) buildBezierPath\n"); - printf("{\n"); - printf(" UIBezierPath *path = [UIBezierPath bezierPath];\n\n"); - - NSArray *elements = self.elements; - for (BezierElement *element in elements) - [element showTheCode]; - - printf(" return path;\n"); - printf("}\n\n"); -} - -- (NSString *) stringValue -{ - NSMutableString *string = [NSMutableString stringWithString:@"\n"]; - NSArray *elements = self.elements; - for (BezierElement *element in elements) - [string appendFormat:@"%@\n", element.stringValue]; - - return string; -} - -#pragma mark - Transformations -// Project point from native to dest -CGPoint adjustPoint(CGPoint p, CGRect native, CGRect dest) -{ - CGFloat scaleX = dest.size.width / native.size.width; - CGFloat scaleY = dest.size.height / native.size.height; - - CGPoint point = PointSubtractPoint(p, native.origin); - point.x *= scaleX; - point.y *= scaleY; - CGPoint destPoint = PointAddPoint(point, dest.origin); - - return destPoint; -} - -// Adjust points by applying block to each element -- (UIBezierPath *) adjustPathElementsWithBlock: (PathBlock) block -{ - UIBezierPath *path = [UIBezierPath bezierPath]; - if (!block) - { - [path appendPath:self]; - return path; - } - - for (BezierElement *element in self.elements) - [[element elementByApplyingBlock:block] addToPath:path]; - - return path; -} - -// Apply transform -- (UIBezierPath *) pathApplyTransform: (CGAffineTransform) transform -{ - UIBezierPath *copy = [UIBezierPath bezierPath]; - [copy appendPath:self]; - - CGRect bounding = self.calculatedBounds; - CGPoint center = RectGetCenter(bounding); - CGAffineTransform t = CGAffineTransformIdentity; - t = CGAffineTransformTranslate(t, center.x, center.y); - t = CGAffineTransformConcat(transform, t); - t = CGAffineTransformTranslate(t, -center.x, -center.y); - [copy applyTransform:t]; - - return copy; -} - -- (CGFloat) pathLength -{ - NSArray *elements = self.elements; - CGPoint current = NULLPOINT; - CGPoint firstPoint = NULLPOINT; - float totalPointLength = 0.0f; - - for (BezierElement *element in elements) - { - totalPointLength += ElementDistanceFromPoint(element, current, firstPoint); - - if (element.elementType == kCGPathElementMoveToPoint) - firstPoint = element.point; - else if (element.elementType == kCGPathElementCloseSubpath) - firstPoint = NULLPOINT; - - if (element.elementType != kCGPathElementCloseSubpath) - current = element.point; - } - - return totalPointLength; -} - - -// Retrieve the point and slope at a given percent offset -- This is expensive -- (CGPoint) pointAtPercent: (CGFloat) percent withSlope: (CGPoint *) slope -{ - NSArray *elements = self.elements; - - if (percent == 0.0f) - { - BezierElement *first = [elements objectAtIndex:0]; - return first.point; - } - - float pathLength = self.pathLength; - float totalDistance = 0.0f; - - CGPoint current = NULLPOINT; - CGPoint firstPoint = NULLPOINT; - - for (BezierElement *element in elements) - { - float distance = ElementDistanceFromPoint(element, current, firstPoint); - CGFloat proposedTotalDistance = totalDistance + distance; - CGFloat proposedPercent = proposedTotalDistance / pathLength; - - if (proposedPercent < percent) - { - // consume and continue - totalDistance = proposedTotalDistance; - - if (element.elementType == kCGPathElementMoveToPoint) - firstPoint = element.point; - - current = element.point; - - continue; - } - - // What percent between p1 and p2? - CGFloat currentPercent = totalDistance / pathLength; - CGFloat dPercent = percent - currentPercent; - CGFloat percentDistance = dPercent * pathLength; - CGFloat targetPercent = percentDistance / distance; - - // Return result - CGPoint point = InterpolatePointFromElement(element, current, firstPoint, targetPercent, slope); - return point; - } - - return NULLPOINT; -} - -#pragma mark - Inverses -- (UIBezierPath *) inverseInRect: (CGRect) rect -{ - UIBezierPath *path = [UIBezierPath bezierPath]; - CopyBezierState(self, path); - [path appendPath:self]; - [path appendPath:[UIBezierPath bezierPathWithRect:rect]]; - path.usesEvenOddFillRule = YES; - return path; -} - -- (UIBezierPath *) inverse -{ - return [self inverseInRect:CGRectInfinite]; -} - -- (UIBezierPath *) boundedInverse -{ - return [self inverseInRect:self.bounds]; -} -@end diff --git a/ios/QuartzBookPack/Drawing/Drawing-Block.h b/ios/QuartzBookPack/Drawing/Drawing-Block.h deleted file mode 100644 index 0f7efb8b..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Block.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import - -typedef void (^DrawingBlock)(CGRect bounds); -typedef void (^DrawingStateBlock)(); -void PushDraw(DrawingStateBlock block); -void PushLayerDraw(DrawingStateBlock block); - - -// Image -UIImage *ImageWithBlock(DrawingBlock block, CGSize size); -UIImage *DrawIntoImage(CGSize size, DrawingStateBlock block); - - -// Blurring -void DrawAndBlur(CGFloat radius, DrawingStateBlock block); diff --git a/ios/QuartzBookPack/Drawing/Drawing-Block.m b/ios/QuartzBookPack/Drawing/Drawing-Block.m deleted file mode 100644 index 0fcaa8c7..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Block.m +++ /dev/null @@ -1,71 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "Drawing-Block.h" -#import "Utility.h" - -#pragma mark - Drawing -UIImage *ImageWithBlock(DrawingBlock block, CGSize size) -{ - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - if (block) block((CGRect){.size = size}); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -void PushDraw(DrawingStateBlock block) -{ - if (!block) return; // nothing to do - - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGContextSaveGState(context); - block(); - CGContextRestoreGState(context); -} - -// Improve performance by pre-clipping context -// before beginning layer drawing -void PushLayerDraw(DrawingStateBlock block) -{ - if (!block) return; // nothing to do - - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGContextBeginTransparencyLayer(context, NULL); - block(); - CGContextEndTransparencyLayer(context); -} - -UIImage *DrawIntoImage(CGSize size, DrawingStateBlock block) -{ - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - if (block) block(); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - - -#define DEBUG_IMAGE(_IMAGE_, _NAME_) [UIImagePNGRepresentation(_IMAGE_) writeToFile:[NSString stringWithFormat:@"/Users/ericasadun/Desktop/%@.png", _NAME_] atomically:YES] - -// Create a blurred drawing group -// Listing 7-4 -void DrawAndBlur(CGFloat radius, DrawingStateBlock block) -{ - if (!block) return; // nothing to do - - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - // Draw and blur the image - UIImage *baseImage = DrawIntoImage(GetUIKitContextSize(), block); - UIImage *blurred = GaussianBlurImage(baseImage, radius); - [blurred drawAtPoint:CGPointZero]; -} \ No newline at end of file diff --git a/ios/QuartzBookPack/Drawing/Drawing-Gradient.h b/ios/QuartzBookPack/Drawing/Drawing-Gradient.h deleted file mode 100644 index 41d29c38..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Gradient.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "BezierFunctions.h" - -#define COLOR_LEVEL(_selector_, _alpha_) [([UIColor _selector_])colorWithAlphaComponent:_alpha_] -#define WHITE_LEVEL(_amt_, _alpha_) [UIColor colorWithWhite:(_amt_) alpha:(_alpha_)] - -// Gradient drawing styles -#define LIMIT_GRADIENT_EXTENT 0 -#define BEFORE_START kCGGradientDrawsBeforeStartLocation -#define AFTER_END kCGGradientDrawsAfterEndLocation -#define KEEP_DRAWING kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation - -typedef __attribute__((NSObject)) CGGradientRef GradientObject; - -@interface Gradient : NSObject -@property (nonatomic, readonly) CGGradientRef gradient; -+ (instancetype) gradientWithColors: (NSArray *) colors locations: (NSArray *) locations; -+ (instancetype) gradientFrom: (UIColor *) color1 to: (UIColor *) color2; - -+ (instancetype) rainbow; -+ (instancetype) linearGloss:(UIColor *) color; -+ (instancetype) gradientUsingInterpolationBlock: (InterpolationBlock) block between: (UIColor *) c1 and: (UIColor *) c2; -+ (instancetype) easeInGradientBetween: (UIColor *) c1 and:(UIColor *) c2; -+ (instancetype) easeInOutGradientBetween: (UIColor *) c1 and:(UIColor *) c2; -+ (instancetype) easeOutGradientBetween: (UIColor *) c1 and:(UIColor *) c2; - -- (void) drawFrom:(CGPoint) p1 toPoint: (CGPoint) p2 style: (int) mask; -- (void) drawRadialFrom:(CGPoint) p1 toPoint: (CGPoint) p2 radii: (CGPoint) radii style: (int) mask; - -- (void) drawTopToBottom: (CGRect) rect; -- (void) drawBottomToTop: (CGRect) rect; -- (void) drawLeftToRight: (CGRect) rect; -- (void) drawFrom:(CGPoint) p1 toPoint: (CGPoint) p2; -- (void) drawAlongAngle: (CGFloat) angle in:(CGRect) rect; - -- (void) drawBasicRadial: (CGRect) rect; -- (void) drawRadialFrom: (CGPoint) p1 toPoint: (CGPoint) p2; -@end; diff --git a/ios/QuartzBookPack/Drawing/Drawing-Gradient.m b/ios/QuartzBookPack/Drawing/Drawing-Gradient.m deleted file mode 100644 index 9e85897e..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Gradient.m +++ /dev/null @@ -1,256 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "Drawing-Gradient.h" -#import "Utility.h" - -@interface Gradient () -@property (nonatomic, strong) GradientObject storedGradient; -@end - -@implementation Gradient - -#pragma mark - Internal -- (CGGradientRef) gradient -{ - return _storedGradient; -} - -#pragma mark - Convenience Creation -+ (instancetype) gradientWithColors: (NSArray *) colorsArray locations: (NSArray *) locationArray -{ - if (!colorsArray) COMPLAIN_AND_BAIL_NIL(@"Missing colors array", nil); - if (!locationArray) COMPLAIN_AND_BAIL_NIL(@"Missing location array", nil); - - CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); - if (space == NULL) - { - NSLog(@"Error: Unable to create device RGB color space"); - return nil; - } - - // Convert locations to CGFloat * - CGFloat locations[locationArray.count]; - for (int i = 0; i < locationArray.count; i++) - locations[i] = [locationArray[i] floatValue]; - - // Convert colors to (id) CGColorRef - NSMutableArray *colorRefArray = [NSMutableArray array]; - for (UIColor *color in colorsArray) - [colorRefArray addObject:(id)color.CGColor]; - - CGGradientRef gradientRef = CGGradientCreateWithColors(space, (__bridge CFArrayRef) colorRefArray, locations); - CGColorSpaceRelease(space); - - if (gradientRef == NULL) - { - NSLog(@"Error: Unable to construct CGGradientRef"); - return nil; - } - - Gradient *gradient = [[self alloc] init]; - gradient.storedGradient = gradientRef; - CGGradientRelease(gradientRef); - - return gradient; -} - -+ (instancetype) gradientFrom: (UIColor *) color1 to: (UIColor *) color2 -{ - return [self gradientWithColors:@[color1, color2] locations:@[@(0.0f), @(1.0f)]]; -} - -#pragma mark - Linear - -- (void) drawRadialFrom:(CGPoint) p1 toPoint: (CGPoint) p2 radii: (CGPoint) radii style: (int) mask -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGContextDrawRadialGradient(context, self.gradient, p1, radii.x, p2, radii.y, mask); -} - -- (void) drawFrom:(CGPoint) p1 toPoint: (CGPoint) p2 style: (int) mask -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGContextDrawLinearGradient(context, self.gradient, p1, p2, mask); -} - -- (void) drawLeftToRight: (CGRect) rect -{ - CGPoint p1 = RectGetMidLeft(rect); - CGPoint p2 = RectGetMidRight(rect); - [self drawFrom:p1 toPoint:p2 style:KEEP_DRAWING]; -} - -- (void) drawTopToBottom: (CGRect) rect -{ - CGPoint p1 = RectGetMidTop(rect); - CGPoint p2 = RectGetMidBottom(rect); - [self drawFrom:p1 toPoint:p2 style:KEEP_DRAWING]; -} - -- (void) drawBottomToTop:(CGRect)rect -{ - CGPoint p1 = RectGetMidBottom(rect); - CGPoint p2 = RectGetMidTop(rect); - [self drawFrom:p1 toPoint:p2 style:KEEP_DRAWING]; -} - -- (void) drawFrom:(CGPoint) p1 toPoint: (CGPoint) p2 -{ - [self drawFrom:p1 toPoint:p2 style:KEEP_DRAWING]; -} - -- (void) drawAlongAngle: (CGFloat) theta in:(CGRect) rect -{ - CGPoint center = RectGetCenter(rect); - CGFloat r = PointDistanceFromPoint(center, RectGetTopRight(rect)); - - CGFloat phi = theta + M_PI; - if (phi > TWO_PI) - phi -= TWO_PI; - - CGFloat dx1 = r * sin(theta); - CGFloat dy1 = r * cos(theta); - CGFloat dx2 = r * sin(phi); - CGFloat dy2 = r * cos(phi); - - CGPoint p1 = CGPointMake(center.x + dx1, center.y + dy1); - CGPoint p2 = CGPointMake(center.x + dx2, center.y + dy2); - [self drawFrom:p1 toPoint:p2]; -} - -#pragma mark - Radial -- (void) drawBasicRadial: (CGRect) rect -{ - CGPoint p1 = RectGetCenter(rect); - CGFloat r = CGRectGetWidth(rect) / 2; - [self drawRadialFrom:p1 toPoint:p1 radii:CGPointMake(0, r) style:KEEP_DRAWING]; -} - -- (void) drawRadialFrom: (CGPoint) p1 toPoint: (CGPoint) p2; -{ - [self drawRadialFrom:p1 toPoint:p1 radii:CGPointMake(0, PointDistanceFromPoint(p1, p2)) style:KEEP_DRAWING]; -} - -#pragma mark - Prebuilt -+ (instancetype) rainbow -{ - NSMutableArray *colors = [NSMutableArray array]; - NSMutableArray *locations = [NSMutableArray array]; - int n = 24; - for (int i = 0; i <= n; i++) - { - CGFloat percent = (CGFloat) i / (CGFloat) n; - CGFloat colorDistance = percent * (CGFloat) (n - 1) / (CGFloat) n; - UIColor *color = [UIColor colorWithHue:colorDistance saturation:1 brightness:1 alpha:1]; - [colors addObject:color]; - [locations addObject:@(percent)]; - } - - return [Gradient gradientWithColors:colors locations:locations]; -} - -+ (instancetype) linearGloss:(UIColor *) color -{ - CGFloat r, g, b, a; - [color getRed:&r green:&g blue:&b alpha:&a]; - - CGFloat l = (0.299f * r + 0.587f * g + 0.114f * b); - CGFloat gloss = pow(l, 0.2) * 0.5; - - CGFloat h, s, v; - [color getHue:&h saturation:&s brightness:&v alpha:NULL]; - s = fminf(s, 0.2f); - - // Rotate by 0.6 PI - CGFloat rHue = ((h < 0.95) && (h > 0.7)) ? 0.67 : 0.17; - CGFloat phi = rHue * M_PI * 2; - CGFloat theta = h * M_PI; - - // Interpolate distance - CGFloat dTheta = (theta - phi); - while (dTheta < 0) dTheta += M_PI * 2; - while (dTheta > 2 * M_PI) dTheta -= M_PI_2; - CGFloat factor = 0.7 + 0.3 * cosf(dTheta); - - // Build highlight colors - UIColor *c1 = [UIColor colorWithHue:h * factor + (1 - factor) * rHue saturation:s brightness:v * factor + (1 - factor) alpha:gloss]; - UIColor *c2 = [c1 colorWithAlphaComponent:0]; - - // Build gradient - NSArray *colors = @[WHITE_LEVEL(1, gloss), WHITE_LEVEL(1, 0.2), c2, c1]; - NSArray *locations = @[@(0.0), @(0.5), @(0.5), @(1)]; - - return [Gradient gradientWithColors:colors locations:locations]; -} - -UIColor *InterpolateBetweenColors(UIColor *c1, UIColor *c2, CGFloat amt) -{ - CGFloat r1, g1, b1, a1; - CGFloat r2, g2, b2, a2; - - if (CGColorGetNumberOfComponents(c1.CGColor) == 4) - [c1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1]; - else - { - [c1 getWhite:&r1 alpha:&a1]; - g1 = r1; b1 = r1; - } - - if (CGColorGetNumberOfComponents(c2.CGColor) == 4) - [c2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2]; - else - { - [c2 getWhite:&r2 alpha:&a2]; - g2 = r2; b2 = r2; - } - - CGFloat r = (r2 * amt) + (r1 * (1.0 - amt)); - CGFloat g = (g2 * amt) + (g1 * (1.0 - amt)); - CGFloat b = (b2 * amt) + (b1 * (1.0 - amt)); - CGFloat a = (a2 * amt) + (a1 * (1.0 - amt)); - return [UIColor colorWithRed:r green:g blue:b alpha:a]; -} - - -+ (instancetype) gradientUsingInterpolationBlock: (InterpolationBlock) block between: (UIColor *) c1 and: (UIColor *) c2; -{ - if (!block) - COMPLAIN_AND_BAIL_NIL(@"Must pass interpolation block", nil); - - NSMutableArray *colors = [NSMutableArray array]; - NSMutableArray *locations = [NSMutableArray array]; - int numberOfSamples = 24; - for (int i = 0; i <= numberOfSamples; i++) - { - CGFloat amt = (CGFloat) i / (CGFloat) numberOfSamples; - CGFloat percentage = Clamp(block(amt), 0.0, 1.0); - [colors addObject:InterpolateBetweenColors(c1, c2, percentage)]; - [locations addObject:@(amt)]; - } - - return [Gradient gradientWithColors:colors locations:locations]; -} - -+ (instancetype) easeInGradientBetween: (UIColor *) c1 and:(UIColor *) c2 -{ - return [self gradientUsingInterpolationBlock:^CGFloat(CGFloat percent) {return EaseIn(percent, 3);} between:c1 and:c2]; -} - -+ (instancetype) easeInOutGradientBetween: (UIColor *) c1 and:(UIColor *) c2 -{ - return [self gradientUsingInterpolationBlock:^CGFloat(CGFloat percent) {return EaseInOut(percent, 3);} between:c1 and:c2]; -} - -+ (instancetype) easeOutGradientBetween: (UIColor *) c1 and:(UIColor *) c2 -{ - return [self gradientUsingInterpolationBlock:^CGFloat(CGFloat percent) {return EaseOut(percent, 3);} between:c1 and:c2]; -} -@end diff --git a/ios/QuartzBookPack/Drawing/Drawing-Util.h b/ios/QuartzBookPack/Drawing/Drawing-Util.h deleted file mode 100644 index fd6ea40a..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Util.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import "Drawing-Gradient.h" - -UIColor *ScaleColorBrightness(UIColor *color, CGFloat amount); - -void DrawStrokedShadowedShape(UIBezierPath *path, UIColor *baseColor, CGRect dest); -void DrawStrokedShadowedText(NSString *string, NSString *fontFace, UIColor *baseColor, CGRect dest); - -void DrawIndentedPath(UIBezierPath *path, UIColor *primary, CGRect rect); -void DrawIndentedText(NSString *string, NSString *fontFace, UIColor *primary, CGRect rect); - -void DrawGradientOverTexture(UIBezierPath *path, UIImage *texture, Gradient *gradient, CGFloat alpha); -void DrawBottomGlow(UIBezierPath *path, UIColor *color, CGFloat percent); -void DrawIconTopLight(UIBezierPath *path, CGFloat p); - -CGSize GetUIKitContextSize(); -UIImage *GradientMaskedReflectionImage(UIImage *sourceImage); -void DrawGradientMaskedReflection(UIImage *image, CGRect rect);; -void ApplyMaskToContext(UIImage *mask); diff --git a/ios/QuartzBookPack/Drawing/Drawing-Util.m b/ios/QuartzBookPack/Drawing/Drawing-Util.m deleted file mode 100644 index 46005dd7..00000000 --- a/ios/QuartzBookPack/Drawing/Drawing-Util.m +++ /dev/null @@ -1,241 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "Drawing-Util.h" -#import "Utility.h" - -UIColor *ScaleColorBrightness(UIColor *color, CGFloat amount) -{ - CGFloat h, s, v, a; - [color getHue:&h saturation:&s brightness:&v alpha:&a]; - CGFloat v1 = Clamp(v * amount, 0, 1); - return [UIColor colorWithHue:h saturation:s brightness:v1 alpha:a]; -} - -void DrawStrokedShadowedShape(UIBezierPath *path, UIColor *baseColor, CGRect dest) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (!context) COMPLAIN_AND_BAIL(@"No context to draw to", nil); - - PushDraw(^{ - CGContextSetShadow(context, CGSizeMake(4, 4), 4); - - PushLayerDraw(^{ - - // Draw letter gradient (to half brightness) - PushDraw(^{ - Gradient *innerGradient = [Gradient gradientFrom:baseColor to:ScaleColorBrightness(baseColor, 0.5)]; - [path addClip]; - [innerGradient drawTopToBottom:path.bounds]; - }); - - // Add the inner shadow with darker color - PushDraw(^{ - CGContextSetBlendMode(context, kCGBlendModeMultiply); - DrawInnerShadow(path, ScaleColorBrightness(baseColor, 0.3), CGSizeMake(0, -2), 2); - }); - - // Stroke with reversed gray gradient - PushDraw(^{ - [path clipToStroke:6]; - [path.inverse addClip]; - Gradient *grayGradient = [Gradient gradientFrom:WHITE_LEVEL(0.0, 1) to:WHITE_LEVEL(0.5, 1)]; - [grayGradient drawTopToBottom:dest]; - }); - - }); - }); -} - -void DrawStrokedShadowedText(NSString *string, NSString *fontFace, UIColor *baseColor, CGRect dest) -{ - // Create text path - UIBezierPath *text = BezierPathFromStringWithFontFace(string, fontFace); - FitPathToRect(text, dest); - DrawStrokedShadowedShape(text, baseColor, dest); -} - - -void DrawIndentedPath(UIBezierPath *path, UIColor *primary, CGRect rect) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (!context) COMPLAIN_AND_BAIL(@"No context to draw to", nil); - - PushDraw(^{ - CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeMultiply); - DrawInnerShadow(path, WHITE_LEVEL(0, 0.4), CGSizeMake(0, 2), 1); - }); - - DrawShadow(path, WHITE_LEVEL(1, 0.5), CGSizeMake(0, 2), 1); - BevelPath(path, WHITE_LEVEL(0, 0.4), 2, 0); - - PushDraw(^{ - [path addClip]; - CGContextSetAlpha(UIGraphicsGetCurrentContext(), 0.3); - - UIColor *secondary = ScaleColorBrightness(primary, 0.3); - Gradient *gradient = [Gradient gradientFrom:primary to:secondary]; - [gradient drawBottomToTop:path.bounds]; - }); - -} - -void DrawIndentedText(NSString *string, NSString *fontFace, UIColor *primary, CGRect rect) -{ - UIBezierPath *letterPath = BezierPathFromStringWithFontFace(string, fontFace); - // RotatePath(letterPath, RadiansFromDegrees(-15)); - FitPathToRect(letterPath, rect); - DrawIndentedPath(letterPath, primary, rect); -} - -void DrawGradientOverTexture(UIBezierPath *path, UIImage *texture, Gradient *gradient, CGFloat alpha) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!texture) COMPLAIN_AND_BAIL(@"Texture cannot be nil", nil); - if (!gradient) COMPLAIN_AND_BAIL(@"Gradient cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGRect rect = path.bounds; - PushDraw(^{ - CGContextSetAlpha(context, alpha); - [path addClip]; - PushLayerDraw(^{ - [texture drawInRect:rect]; - CGContextSetBlendMode(context, kCGBlendModeColor); - [gradient drawTopToBottom:rect]; - }); - }); -} - -void DrawBottomGlow(UIBezierPath *path, UIColor *color, CGFloat percent) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - if (!color) COMPLAIN_AND_BAIL(@"Color cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGRect rect = path.calculatedBounds; - CGPoint h1 = RectGetPointAtPercents(rect, 0.5f, 1.0f); - CGPoint h2 = RectGetPointAtPercents(rect, 0.5f, 1.0f - percent); - - Gradient *gradient = [Gradient easeInOutGradientBetween:color and:[color colorWithAlphaComponent:0.0f]]; - - PushDraw(^{ - [path addClip]; - [gradient drawFrom:h1 toPoint:h2]; - }); -} - -void DrawIconTopLight(UIBezierPath *path, CGFloat p) -{ - if (!path) COMPLAIN_AND_BAIL(@"Path cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - CGFloat percent = 1.0f - p; - CGRect rect = path.bounds; - CGRect offset = rect; - offset.origin.y -= percent * offset.size.height; - offset = CGRectInset(offset, -offset.size.width * 0.3f, 0); - - UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect:offset]; - Gradient *gradient = [Gradient gradientFrom:WHITE_LEVEL(1, 0.0) to: WHITE_LEVEL(1, 0.5)]; - - PushDraw(^{ - [path addClip]; - [ovalPath addClip]; - - // Draw gradient - CGPoint p1 = RectGetPointAtPercents(rect, 0.5, 0.0); - CGPoint p2 = RectGetPointAtPercents(ovalPath.bounds, 0.5, 1); - [gradient drawFrom:p1 toPoint:p2]; - }); -} - -CGSize GetQuartzContextSize() -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) return CGSizeZero; - return CGSizeMake(CGBitmapContextGetWidth(context), CGBitmapContextGetHeight(context)); -} - -// Listing 7-4 -CGSize GetUIKitContextSize() -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) return CGSizeZero; - CGSize size = CGSizeMake(CGBitmapContextGetWidth(context), CGBitmapContextGetHeight(context)); - CGFloat scale = [UIScreen mainScreen].scale; - return CGSizeMake(size.width / scale, size.height / scale); -} - -void ApplyMaskToContext(UIImage *mask) -{ - if (!mask) COMPLAIN_AND_BAIL(@"Mask cannot be nil", nil); - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to apply mask to", nil); - - // Ensure that mask is grayscale - UIImage *gray = GrayscaleVersionOfImage(mask); - CGSize contextSize = GetUIKitContextSize(); - - // Clipping takes place in Quartz space, so flip before applying - FlipContextVertically(contextSize); - CGContextClipToMask(context, SizeMakeRect(contextSize), gray.CGImage); - FlipContextVertically(contextSize); -} - -UIImage *ApplyMaskToImage(UIImage *image, UIImage *mask) -{ - if (!image) COMPLAIN_AND_BAIL_NIL(@"Image cannot be nil", nil); - if (!mask) COMPLAIN_AND_BAIL_NIL(@"Mask cannot be nil", nil); - - UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0); - ApplyMaskToContext(mask); - [image drawInRect:SizeMakeRect(image.size)]; - UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return result; -} - -UIImage *GradientImage(CGSize size, UIColor *c1, UIColor *c2) -{ - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - - Gradient *gradient = [Gradient gradientFrom:c1 to:c2]; - [gradient drawTopToBottom:SizeMakeRect(size)]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -UIImage *GradientMaskedReflectionImage(UIImage *sourceImage) -{ - UIImage *mirror = ImageMirroredVertically(sourceImage); - UIImage *gradImage = GrayscaleVersionOfImage(GradientImage(sourceImage.size, WHITE_LEVEL(1, 0.5), WHITE_LEVEL(0, 0.5))); - UIImage *masked = ApplyMaskToImage(mirror, gradImage); - return masked; -} - -// Listing 7-5 -void DrawGradientMaskedReflection(UIImage *image, CGRect rect) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - UIImage *gradient = GradientImage(rect.size, WHITE_LEVEL(1, 0.5), WHITE_LEVEL(1, 0.0)); - PushDraw(^{ - CGContextTranslateCTM(context, 0, rect.origin.y); - FlipContextVertically(rect.size); - CGContextTranslateCTM(context, 0, -rect.origin.y); - CGContextClipToMask(context, rect, gradient.CGImage); - [image drawInRect:rect]; - }); -} - - diff --git a/ios/QuartzBookPack/Geometry/BaseGeometry.h b/ios/QuartzBookPack/Geometry/BaseGeometry.h deleted file mode 100644 index b52f6bea..00000000 --- a/ios/QuartzBookPack/Geometry/BaseGeometry.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ -#import -#import -// Just because -#define TWO_PI (2 * M_PI) - -// Undefined point -#define NULLPOINT CGRectNull.origin -#define POINT_IS_NULL(_POINT_) CGPointEqualToPoint(_POINT_, NULLPOINT) - -// General -#define RECTSTRING(_aRect_) NSStringFromCGRect(_aRect_) -#define POINTSTRING(_aPoint_) NSStringFromCGPoint(_aPoint_) -#define SIZESTRING(_aSize_) NSStringFromCGSize(_aSize_) - -#define RECT_WITH_SIZE(_SIZE_) (CGRect){.size = _SIZE_} -#define RECT_WITH_POINT(_POINT_) (CGRect){.origin = _POINT_} - -// Conversion -CGFloat DegreesFromRadians(CGFloat radians); -CGFloat RadiansFromDegrees(CGFloat degrees); - -// Clamping -CGFloat Clamp(CGFloat a, CGFloat min, CGFloat max); -CGPoint ClampToRect(CGPoint pt, CGRect rect); - -// General Geometry -CGPoint RectGetCenter(CGRect rect); -CGFloat PointDistanceFromPoint(CGPoint p1, CGPoint p2); - -// Construction -CGRect RectMakeRect(CGPoint origin, CGSize size); -CGRect SizeMakeRect(CGSize size); -CGRect PointsMakeRect(CGPoint p1, CGPoint p2); -CGRect OriginMakeRect(CGPoint origin); -CGRect RectAroundCenter(CGPoint center, CGSize size); -CGRect RectCenteredInRect(CGRect rect, CGRect mainRect); - -// Point Locations -CGPoint RectGetPointAtPercents(CGRect rect, CGFloat xPercent, CGFloat yPercent); -CGPoint PointAddPoint(CGPoint p1, CGPoint p2); -CGPoint PointSubtractPoint(CGPoint p1, CGPoint p2); - -// Cardinal Points -CGPoint RectGetTopLeft(CGRect rect); -CGPoint RectGetTopRight(CGRect rect); -CGPoint RectGetBottomLeft(CGRect rect); -CGPoint RectGetBottomRight(CGRect rect); -CGPoint RectGetMidTop(CGRect rect); -CGPoint RectGetMidBottom(CGRect rect); -CGPoint RectGetMidLeft(CGRect rect); -CGPoint RectGetMidRight(CGRect rect); - -// Aspect and Fitting -CGSize SizeScaleByFactor(CGSize aSize, CGFloat factor); -CGSize RectGetScale(CGRect sourceRect, CGRect destRect); -CGFloat AspectScaleFill(CGSize sourceSize, CGRect destRect); -CGFloat AspectScaleFit(CGSize sourceSize, CGRect destRect); -CGRect RectByFittingRect(CGRect sourceRect, CGRect destinationRect); -CGRect RectByFillingRect(CGRect sourceRect, CGRect destinationRect); -CGRect RectInsetByPercent(CGRect rect, CGFloat percent); - -// Transforms -CGFloat TransformGetXScale(CGAffineTransform t); -CGFloat TransformGetYScale(CGAffineTransform t); -CGFloat TransformGetRotation(CGAffineTransform t); diff --git a/ios/QuartzBookPack/Geometry/BaseGeometry.m b/ios/QuartzBookPack/Geometry/BaseGeometry.m deleted file mode 100644 index 6e8b655d..00000000 --- a/ios/QuartzBookPack/Geometry/BaseGeometry.m +++ /dev/null @@ -1,242 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "BaseGeometry.h" - -#pragma mark - Conversion -// Degrees from radians -CGFloat DegreesFromRadians(CGFloat radians) -{ - return radians * 180.0f / M_PI; -} - -// Radians from degrees -CGFloat RadiansFromDegrees(CGFloat degrees) -{ - return degrees * M_PI / 180.0f; -} - -#pragma mark - Clamp -CGFloat Clamp(CGFloat a, CGFloat min, CGFloat max) -{ - return fmin(fmax(min, a), max); -} - -CGPoint ClampToRect(CGPoint pt, CGRect rect) -{ - CGFloat x = Clamp(pt.x, CGRectGetMinX(rect), CGRectGetMaxX(rect)); - CGFloat y = Clamp(pt.y, CGRectGetMinY(rect), CGRectGetMaxY(rect)); - return CGPointMake(x, y); -} - - -#pragma mark - General Geometry -CGPoint RectGetCenter(CGRect rect) -{ - return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); -} - -CGFloat PointDistanceFromPoint(CGPoint p1, CGPoint p2) -{ - CGFloat dx = p2.x - p1.x; - CGFloat dy = p2.y - p1.y; - - return sqrt(dx*dx + dy*dy); -} - -CGPoint RectGetPointAtPercents(CGRect rect, CGFloat xPercent, CGFloat yPercent) -{ - CGFloat dx = xPercent * rect.size.width; - CGFloat dy = yPercent * rect.size.height; - return CGPointMake(rect.origin.x + dx, rect.origin.y + dy); -} - -#pragma mark - Rectangle Construction -CGRect RectMakeRect(CGPoint origin, CGSize size) -{ - return (CGRect){.origin = origin, .size = size}; -} - -CGRect SizeMakeRect(CGSize size) -{ - return (CGRect){.size = size}; -} - -CGRect PointsMakeRect(CGPoint p1, CGPoint p2) -{ - CGRect rect = CGRectMake(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y); - return CGRectStandardize(rect); -} - -CGRect OriginMakeRect(CGPoint origin) -{ - return (CGRect){.origin = origin}; -} - -CGRect RectAroundCenter(CGPoint center, CGSize size) -{ - CGFloat halfWidth = size.width / 2.0f; - CGFloat halfHeight = size.height / 2.0f; - - return CGRectMake(center.x - halfWidth, center.y - halfHeight, size.width, size.height); -} - -CGRect RectCenteredInRect(CGRect rect, CGRect mainRect) -{ - CGFloat dx = CGRectGetMidX(mainRect)-CGRectGetMidX(rect); - CGFloat dy = CGRectGetMidY(mainRect)-CGRectGetMidY(rect); - return CGRectOffset(rect, dx, dy); -} - -#pragma mark - Point Location -CGPoint PointAddPoint(CGPoint p1, CGPoint p2) -{ - return CGPointMake(p1.x + p2.x, p1.y + p2.y); -} - -CGPoint PointSubtractPoint(CGPoint p1, CGPoint p2) -{ - return CGPointMake(p1.x - p2.x, p1.y - p2.y); -} - -#pragma mark - Cardinal Points -CGPoint RectGetTopLeft(CGRect rect) -{ - return CGPointMake( - CGRectGetMinX(rect), - CGRectGetMinY(rect) - ); -} - -CGPoint RectGetTopRight(CGRect rect) -{ - return CGPointMake( - CGRectGetMaxX(rect), - CGRectGetMinY(rect) - ); -} - -CGPoint RectGetBottomLeft(CGRect rect) -{ - return CGPointMake( - CGRectGetMinX(rect), - CGRectGetMaxY(rect) - ); -} - -CGPoint RectGetBottomRight(CGRect rect) -{ - return CGPointMake( - CGRectGetMaxX(rect), - CGRectGetMaxY(rect) - ); -} - -CGPoint RectGetMidTop(CGRect rect) -{ - return CGPointMake( - CGRectGetMidX(rect), - CGRectGetMinY(rect) - ); -} - -CGPoint RectGetMidBottom(CGRect rect) -{ - return CGPointMake( - CGRectGetMidX(rect), - CGRectGetMaxY(rect) - ); -} - -CGPoint RectGetMidLeft(CGRect rect) -{ - return CGPointMake( - CGRectGetMinX(rect), - CGRectGetMidY(rect) - ); -} - -CGPoint RectGetMidRight(CGRect rect) -{ - return CGPointMake( - CGRectGetMaxX(rect), - CGRectGetMidY(rect) - ); -} - -#pragma mark - Aspect and Fitting -CGSize SizeScaleByFactor(CGSize aSize, CGFloat factor) -{ - return CGSizeMake(aSize.width * factor, aSize.height * factor); -} - -CGSize RectGetScale(CGRect sourceRect, CGRect destRect) -{ - CGSize sourceSize = sourceRect.size; - CGSize destSize = destRect.size; - - CGFloat scaleW = destSize.width / sourceSize.width; - CGFloat scaleH = destSize.height / sourceSize.height; - - return CGSizeMake(scaleW, scaleH); -} - -CGFloat AspectScaleFill(CGSize sourceSize, CGRect destRect) -{ - CGSize destSize = destRect.size; - CGFloat scaleW = destSize.width / sourceSize.width; - CGFloat scaleH = destSize.height / sourceSize.height; - return fmax(scaleW, scaleH); -} - -CGFloat AspectScaleFit(CGSize sourceSize, CGRect destRect) -{ - CGSize destSize = destRect.size; - CGFloat scaleW = destSize.width / sourceSize.width; - CGFloat scaleH = destSize.height / sourceSize.height; - return fmin(scaleW, scaleH); -} - -CGRect RectByFittingRect(CGRect sourceRect, CGRect destinationRect) -{ - CGFloat aspect = AspectScaleFit(sourceRect.size, destinationRect); - CGSize targetSize = SizeScaleByFactor(sourceRect.size, aspect); - return RectAroundCenter(RectGetCenter(destinationRect), targetSize); -} - -CGRect RectByFillingRect(CGRect sourceRect, CGRect destinationRect) -{ - CGFloat aspect = AspectScaleFill(sourceRect.size, destinationRect); - CGSize targetSize = SizeScaleByFactor(sourceRect.size, aspect); - return RectAroundCenter(RectGetCenter(destinationRect), targetSize); -} - -CGRect RectInsetByPercent(CGRect rect, CGFloat percent) -{ - CGFloat wInset = rect.size.width * (percent / 2.0f); - CGFloat hInset = rect.size.height * (percent / 2.0f); - return CGRectInset(rect, wInset, hInset); -} - -#pragma mark - Transforms - -// Extract the x scale from transform -CGFloat TransformGetXScale(CGAffineTransform t) -{ - return sqrt(t.a * t.a + t.c * t.c); -} - -// Extract the y scale from transform -CGFloat TransformGetYScale(CGAffineTransform t) -{ - return sqrt(t.b * t.b + t.d * t.d); -} - -// Extract the rotation in radians -CGFloat TransformGetRotation(CGAffineTransform t) -{ - return atan2f(t.b, t.a); -} diff --git a/ios/QuartzBookPack/Image/ImageUtils.h b/ios/QuartzBookPack/Image/ImageUtils.h deleted file mode 100644 index f70ab1eb..00000000 --- a/ios/QuartzBookPack/Image/ImageUtils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - Gathered for book examples - - */ - -#import -#import - -// 4 bytes per ARGB pixel, 8 bits per byte -#define ARGB_COUNT 4 -#define BITS_PER_COMPONENT 8 - -UIEdgeInsets BuildInsets(CGRect alignmentRect, CGRect imageBounds); - -UIImage *BuildSwatchWithColor(UIColor *color, CGFloat side); -UIImage *BuildThumbnail(UIImage *sourceImage, CGSize targetSize, BOOL useFitting); -UIImage *ExtractRectFromImage(UIImage *sourceImage, CGRect subRect); -UIImage *ExtractSubimageFromRect(UIImage *sourceImage, CGRect rect); - -UIImage *GrayscaleVersionOfImage(UIImage *sourceImage); -UIImage *InvertImage(UIImage *sourceImage); - -NSData *BytesFromRGBImage(UIImage *sourceImage); -UIImage *ImageFromRGBBytes(NSData *data, CGSize targetSize); - -void FlipContextVertically(CGSize size); -void FlipContextHorizontally(CGSize size); -void FlipImageContextVertically(); -void FlipImageContextHorizontally(); -void RotateContext(CGSize size, CGFloat theta); -void MoveContextByVector(CGPoint vector); - -UIImage *ImageMirroredVertically(UIImage *image); - -void DrawPDFPageInRect(CGPDFPageRef pageRef, CGRect destinationRect); - -UIImage *GaussianBlurImage(UIImage *image, CGFloat radius); diff --git a/ios/QuartzBookPack/Image/ImageUtils.m b/ios/QuartzBookPack/Image/ImageUtils.m deleted file mode 100644 index d108fd7d..00000000 --- a/ios/QuartzBookPack/Image/ImageUtils.m +++ /dev/null @@ -1,372 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "ImageUtils.h" -#import "Utility.h" -#import "BaseGeometry.h" - -// Chapter 3-8 -// Establish insets for image alignment -UIEdgeInsets BuildInsets(CGRect alignmentRect, CGRect imageBounds) -{ - // Ensure alignment rect is fully within source - CGRect targetRect = CGRectIntersection(alignmentRect, imageBounds); - - // Calculate insets - UIEdgeInsets insets; - insets.left = CGRectGetMinX(targetRect) - CGRectGetMinX(imageBounds); - insets.right = CGRectGetMaxX(imageBounds) - CGRectGetMaxX(targetRect); - insets.top = CGRectGetMinY(targetRect) - CGRectGetMinY(imageBounds); - insets.bottom = CGRectGetMaxY(imageBounds) - CGRectGetMaxY(targetRect); - - return insets; -} - - -// Chapter 3 - 1 -UIImage *BuildSwatchWithColor(UIColor *color, CGFloat side) -{ - // Create image context - UIGraphicsBeginImageContextWithOptions( - CGSizeMake(side, side), YES, - 0.0); - - // Perform drawing - [color setFill]; - UIRectFill(CGRectMake(0, 0, side, side)); - - // Retrieve image - UIImage *image = - UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -// Chapter 3 - 2 -UIImage *BuildThumbnail(UIImage *sourceImage, CGSize targetSize, BOOL useFitting) -{ - CGRect targetRect = SizeMakeRect(targetSize); - UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0); - - CGRect naturalRect = (CGRect){.size = sourceImage.size}; - CGRect destinationRect = useFitting ? RectByFittingRect(naturalRect, targetRect) : RectByFillingRect(naturalRect, targetRect); - [sourceImage drawInRect:destinationRect]; - - UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return thumbnail; -} - -// Chapter 3 - 3 -UIImage *ExtractRectFromImage(UIImage *sourceImage, CGRect subRect) -{ - // Extract image - CGImageRef imageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, subRect); - if (imageRef != NULL) - { - UIImage *output = [UIImage imageWithCGImage:imageRef]; - CGImageRelease(imageRef); - return output; - } - - NSLog(@"Error: Unable to extract subimage"); - return nil; -} - -// This is a little less flaky when moving to and from Retina images -UIImage *ExtractSubimageFromRect(UIImage *sourceImage, CGRect rect) -{ - UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1); - CGRect destRect = CGRectMake(-rect.origin.x, -rect.origin.y, - sourceImage.size.width, sourceImage.size.height); - [sourceImage drawInRect:destRect]; - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return newImage; -} - -// Chapter 3 - 4 -UIImage *GrayscaleVersionOfImage(UIImage *sourceImage) -{ - // Establish grayscale color space - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); - if (colorSpace == NULL) - { - NSLog(@"Error: Could not establish grayscale color space"); - return nil; - } - - // Extents are integers - int width = sourceImage.size.width; - int height = sourceImage.size.height; - - // Build context: one byte per pixel, no alpha - CGContextRef context = CGBitmapContextCreate(NULL, width, height, BITS_PER_COMPONENT, width, colorSpace, (CGBitmapInfo)kCGImageAlphaNone); - CGColorSpaceRelease(colorSpace); - if (context == NULL) - { - NSLog(@"Error: Could not build grayscale bitmap context"); - return nil; - } - - // Replicate image using new color space - CGRect rect = SizeMakeRect(sourceImage.size); - CGContextDrawImage(context, rect, sourceImage.CGImage); - CGImageRef imageRef = CGBitmapContextCreateImage(context); - CGContextRelease(context); - - // Return the grayscale image - UIImage *output = [UIImage imageWithCGImage:imageRef]; - CFRelease(imageRef); - return output; -} - -// Just for fun. Return image with colors flipped -UIImage *InvertImage(UIImage *sourceImage) -{ - UIGraphicsBeginImageContextWithOptions(sourceImage.size, NO, 0.0); - CGContextRef context = UIGraphicsGetCurrentContext(); - [sourceImage drawInRect:SizeMakeRect(sourceImage.size)]; - CGContextSetBlendMode(context, kCGBlendModeDifference); - CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor); - CGContextFillRect(context, SizeMakeRect(sourceImage.size)); - UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return result; -} - -// Chapter 3-6 -// Extract bytes -NSData *BytesFromRGBImage(UIImage *sourceImage) -{ - if (!sourceImage) return nil; - - // Establish color space - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if (colorSpace == NULL) - { - NSLog(@"Error creating RGB color space"); - return nil; - } - - // Establish context - int width = sourceImage.size.width; - int height = sourceImage.size.height; - CGContextRef context = CGBitmapContextCreate(NULL, width, height, BITS_PER_COMPONENT, width * ARGB_COUNT, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(colorSpace ); - if (context == NULL) - { - NSLog(@"Error creating context"); - return nil; - } - - // Draw source into context bytes - CGRect rect = (CGRect){.size = sourceImage.size}; - CGContextDrawImage(context, rect, sourceImage.CGImage); - - // Create NSData from bytes - NSData *data = [NSData dataWithBytes:CGBitmapContextGetData(context) length:(width * height * 4)]; - CGContextRelease(context); - - return data; -} - -// Chapter 3-7 -// Create image from bytes -UIImage *ImageFromRGBBytes(NSData *data, CGSize targetSize) -{ - // Check data - int width = targetSize.width; - int height = targetSize.height; - if (data.length < (width * height * 4)) - { - NSLog(@"Error: Not enough RGB data provided. Got %d bytes. Expected %d bytes", data.length, width * height * 4); - return nil; - } - - // Create a color space - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - if (colorSpace == NULL) - { - NSLog(@"Error creating RGB colorspace"); - return nil; - } - - // Create the bitmap context - Byte *bytes = (Byte *) data.bytes; - CGContextRef context = CGBitmapContextCreate(bytes, width, height, BITS_PER_COMPONENT, width * ARGB_COUNT, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(colorSpace ); - if (context == NULL) - { - NSLog(@"Error. Could not create context"); - return nil; - } - - // Convert to image - CGImageRef imageRef = CGBitmapContextCreateImage(context); - UIImage *image = [UIImage imageWithCGImage:imageRef]; - - // Clean up - CGContextRelease(context); - CFRelease(imageRef); - - return image; -} - -#pragma mark - Context - -// From Chapter 1 -void FlipContextVertically(CGSize size) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) - { - NSLog(@"Error: No context to flip"); - return; - } - - CGAffineTransform transform = CGAffineTransformIdentity; - transform = CGAffineTransformScale(transform, 1.0f, -1.0f); - transform = CGAffineTransformTranslate(transform, 0.0f, -size.height); - CGContextConcatCTM(context, transform); -} - -void FlipImageContextVertically() -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) - { - NSLog(@"Error: No context to flip"); - return; - } - - // I don't like this approach - // CGFloat scale = [UIScreen mainScreen].scale; - // CGSize size = CGSizeMake(CGBitmapContextGetWidth(context) / scale, CGBitmapContextGetHeight(context) / scale); - // FlipContextVertically(size); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - FlipContextVertically(image.size); -} - -void FlipContextHorizontally(CGSize size) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - CGAffineTransform transform = CGAffineTransformIdentity; - transform = CGAffineTransformScale(transform, -1.0f, 1.0f); - transform = CGAffineTransformTranslate(transform, -size.width, 0.0); - CGContextConcatCTM(context, transform); -} - -void FlipImageContextHorizontally() -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) - { - NSLog(@"Error: No context to flip"); - return; - } - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - FlipContextHorizontally(image.size); -} - -void RotateContext(CGSize size, CGFloat theta) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextTranslateCTM(context, size.width / 2.0f, size.height / 2.0f); - CGContextRotateCTM(context, theta); - CGContextTranslateCTM(context, -size.width / 2.0f, -size.height / 2.0f); -} - -void MoveContextByVector(CGPoint vector) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextTranslateCTM(context, vector.x, vector.y); -} - -UIImage *ImageMirroredVertically(UIImage *source) -{ - UIGraphicsBeginImageContextWithOptions(source.size, NO, 0.0); - FlipContextVertically(source.size); - [source drawInRect:SizeMakeRect(source.size)]; - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - - -#pragma mark - PDF Util -// Chapter 3-12 -void DrawPDFPageInRect(CGPDFPageRef pageRef, CGRect destinationRect) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) - { - NSLog(@"Error: No context to draw to"); - return; - } - - CGContextSaveGState(context); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - - // Flip the context to Quartz space - CGAffineTransform transform = CGAffineTransformIdentity; - transform = CGAffineTransformScale(transform, 1.0f, -1.0f); - transform = CGAffineTransformTranslate(transform, 0.0f, -image.size.height); - CGContextConcatCTM(context, transform); - - // Flip the rect, which remains in UIKit space - CGRect d = CGRectApplyAffineTransform(destinationRect, transform); - - // Calculate a rectangle to draw to - CGRect pageRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox); - CGFloat drawingAspect = AspectScaleFit(pageRect.size, d); - CGRect drawingRect = RectByFittingRect(pageRect, d); - - // Draw the page outline (optional) - UIRectFrame(drawingRect); - - // Adjust the context - CGContextTranslateCTM(context, drawingRect.origin.x, drawingRect.origin.y); - CGContextScaleCTM(context, drawingAspect, drawingAspect); - - // Draw the page - CGContextDrawPDFPage(context, pageRef); - CGContextRestoreGState(context); -} - -#pragma mark - Masking, Blurring -// Listing 7-3 -UIImage *GaussianBlurImage(UIImage *image, CGFloat radius) -{ - if (!image) COMPLAIN_AND_BAIL_NIL(@"Mask cannot be nil", nil); - - CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; - [blurFilter setValue: [CIImage imageWithCGImage:image.CGImage] - forKey: @"inputImage"]; - [blurFilter setValue:@(radius) forKey:@"inputRadius"]; - - CIFilter *crop = [CIFilter filterWithName: @"CICrop"]; - [crop setDefaults]; - [crop setValue:blurFilter.outputImage forKey:@"inputImage"]; - - CGFloat scale = [[UIScreen mainScreen] scale]; - CGFloat w = image.size.width * scale; - CGFloat h = image.size.height * scale; - CIVector *v = [CIVector vectorWithX:0 Y:0 Z:w W:h]; - [crop setValue:v forKey:@"inputRectangle"]; - - CGImageRef cgImageRef = [[CIContext contextWithOptions:nil] createCGImage:crop.outputImage fromRect:crop.outputImage.extent]; - - UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0); - FlipContextVertically(image.size); - CGContextDrawImage(UIGraphicsGetCurrentContext(), SizeMakeRect(image.size), cgImageRef); - UIImage *blurred = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return blurred; -} \ No newline at end of file diff --git a/ios/QuartzBookPack/TextDrawing/Drawing-Text.h b/ios/QuartzBookPack/TextDrawing/Drawing-Text.h deleted file mode 100644 index 00b4fae9..00000000 --- a/ios/QuartzBookPack/TextDrawing/Drawing-Text.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import -@import Foundation; -@import CoreText; - -#import "Drawing-Text.h" - -// Sizing -NSArray *WidthArrayForStringWithFont(NSString *string, UIFont *font); - -// Drawing -void DrawStringInRect(NSString *string, CGRect rect, UIFont *font, NSTextAlignment alignment, UIColor *color); -void DrawWrappedStringInRect(NSString *string, CGRect rect, NSString *fontFace, NSTextAlignment alignment, UIColor *color); -void DrawUnwrappedStringInRect(NSString *string, CGRect rect, NSString *fontFace, NSTextAlignment alignment, UIColor *color); -void DrawStringCenteredInRect(NSString *string, UIFont *font, CGRect rect); - -UIFont *FontForWrappedString(NSString *string, NSString *fontFace, CGRect rect, CGFloat tolerance); diff --git a/ios/QuartzBookPack/TextDrawing/Drawing-Text.m b/ios/QuartzBookPack/TextDrawing/Drawing-Text.m deleted file mode 100644 index 46599674..00000000 --- a/ios/QuartzBookPack/TextDrawing/Drawing-Text.m +++ /dev/null @@ -1,175 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import "Drawing-Text.h" -#import "Utility.h" - -#pragma mark - Drawing - -void DrawStringInRect(NSString *string, CGRect rect, UIFont *font, NSTextAlignment alignment, UIColor *color) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) return; - - NSRange range = NSMakeRange(0, string.length); - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; - - NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; - NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - style.alignment = alignment; - style.lineBreakMode = NSLineBreakByWordWrapping; - attributes[NSFontAttributeName] = font; - attributes[NSForegroundColorAttributeName] = color; - attributes[NSParagraphStyleAttributeName] = style; - [attributedString addAttributes:attributes range:range]; - - CGRect destRect = [string boundingRectWithSize:CGSizeMake(rect.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; - CGRect outputRect = RectCenteredInRect(destRect, rect); - [attributedString drawInRect:outputRect]; -} - -#pragma mark - Unwrapped -UIFont *FontForUnwrappedString(NSString *string, NSString *fontFace, CGRect rect) -{ - CGFloat fontSize = 1; - UIFont *font = [UIFont fontWithName:fontFace size:fontSize]; - CGSize destSize = [string sizeWithAttributes:@{NSFontAttributeName:font}]; - - while ((destSize.width < rect.size.width) && (destSize.height < rect.size.height)) - { - fontSize++; - UIFont *proposedFont = [UIFont fontWithName:fontFace size:fontSize]; - destSize = [string sizeWithAttributes:@{NSFontAttributeName:proposedFont}]; - if ((destSize.height > rect.size.height) || (destSize.width > rect.size.width)) - return font; - - font = proposedFont; - } - - return font; -} - -void DrawUnwrappedStringInRect(NSString *string, CGRect rect, NSString *fontFace, NSTextAlignment alignment, UIColor *color) -{ - UIFont *font = FontForUnwrappedString(string, fontFace, rect); - DrawStringInRect(string, rect, font, alignment, color); -} - -void DrawStringCenteredInRect(NSString *string, UIFont *font, CGRect rect) -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - // Calculate string size - CGSize stringSize = [string sizeWithAttributes:@{NSFontAttributeName:font}]; - - // Find the target rectangle - CGRect target = RectAroundCenter(RectGetCenter(rect), stringSize); - - // Draw the string - [string drawInRect:target withAttributes:@{NSFontAttributeName:font}]; -} - - -#pragma mark - Wrapping - -UIFont *FontForWrappedString(NSString *string, NSString *fontFace, CGRect rect, CGFloat tolerance) -{ - if (rect.size.height < 1.0f) return nil; - - CGFloat adjustedWidth = tolerance * rect.size.width; - CGSize measureSize = CGSizeMake(adjustedWidth, CGFLOAT_MAX); - - // Initialize the proposed font - CGFloat fontSize = 1; - UIFont *proposedFont = [UIFont fontWithName:fontFace size:fontSize]; - - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; - - NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; - attributes[NSParagraphStyleAttributeName] = paragraphStyle; - attributes[NSFontAttributeName] = proposedFont; - - // Measure the target - CGSize targetSize = [string boundingRectWithSize:measureSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; - - // Double until the size is exceeded - while (targetSize.height <= rect.size.height) - { - // Establish a new proposed font - fontSize *= 2; - proposedFont = [UIFont fontWithName:fontFace size:fontSize]; - - // Measure the target - attributes[NSFontAttributeName] = proposedFont; - targetSize = [string boundingRectWithSize:measureSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; - - // Break when the calculated height is too much - if (targetSize.height > rect.size.height) - break; - } - - // Search between the previous and current font sizes - CGFloat minFontSize = fontSize / 2; - CGFloat maxFontSize = fontSize; - while (1) - { - // Get the midpoint between the two - CGFloat midPoint = (minFontSize + (maxFontSize - minFontSize) / 2); - proposedFont = [UIFont fontWithName:fontFace size:midPoint]; - attributes[NSFontAttributeName] = proposedFont; - targetSize = [string boundingRectWithSize:measureSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; - - // Look up one font size - UIFont *nextFont = [UIFont fontWithName:fontFace size:midPoint + 1]; - attributes[NSFontAttributeName] = nextFont; - CGSize nextTargetSize = [string boundingRectWithSize:measureSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;; - - // Test both fonts - CGFloat tooBig = targetSize.height > rect.size.height; - CGFloat nextIsTooBig = nextTargetSize.height > rect.size.height; - - // If the current is sized right but the next is too big, win - if (!tooBig && nextIsTooBig) - return [UIFont fontWithName:fontFace size:midPoint]; - - // Adjust the search space - if (tooBig) - maxFontSize = midPoint; - else - minFontSize = midPoint; - } - - // Should never get here - return [UIFont fontWithName:fontFace size:fontSize / 2]; -} - -CGSize AttributedStringSize(NSAttributedString *string, CGSize constrainedSize) -{ - return [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; -} - -void DrawWrappedStringInRect(NSString *string, CGRect rect, NSString *fontFace, NSTextAlignment alignment, UIColor *color) -{ - - UIFont *font = FontForWrappedString(string, fontFace, rect, 0.95); - - NSMutableAttributedString *s = [[NSMutableAttributedString alloc] initWithString:string]; - NSRange r = NSMakeRange(0, string.length); - [s addAttribute:NSFontAttributeName value:font range:r]; - [s addAttribute:NSForegroundColorAttributeName value:color range:r]; - NSMutableParagraphStyle *p = [NSParagraphStyle defaultParagraphStyle].mutableCopy; - p.hyphenationFactor = 0.25f; - p.alignment = alignment; - [s addAttribute:NSParagraphStyleAttributeName value:p range:r]; - - CGRect stringBounds = SizeMakeRect(AttributedStringSize(s, rect.size)); - stringBounds.size.width = fminf(rect.size.width, stringBounds.size.width); - CGRect dest = RectCenteredInRect(stringBounds, rect); - dest.size.height = CGFLOAT_MAX; - [s drawInRect:dest]; -} \ No newline at end of file diff --git a/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.h b/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.h deleted file mode 100644 index 6fa0befd..00000000 --- a/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - Erica Sadun, http://ericasadun.com - iPhone Developer's Cookbook, 6.x Edition - BSD License, Use at your own risk - */ - -#import -#import - -#import "UIBezierPath+Elements.h" -@interface UIBezierPath (TextUtilities) -- (void) drawAttributedString: (NSAttributedString *) string; -@end diff --git a/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.m b/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.m deleted file mode 100644 index 9d893e66..00000000 --- a/ios/QuartzBookPack/TextDrawing/UIBezierPath+Text.m +++ /dev/null @@ -1,56 +0,0 @@ -/* - Erica Sadun, http://ericasadun.com - iPhone Developer's Cookbook, 6.x Edition - BSD License, Use at your own risk - */ - -#import "UIBezierPath+Text.h" -#import "Utility.h" - -@implementation UIBezierPath (TextUtilities) -- (void) drawAttributedString: (NSAttributedString *) string -{ - if (!string) return; - CGContextRef context = UIGraphicsGetCurrentContext(); - if (context == NULL) COMPLAIN_AND_BAIL(@"No context to draw into", nil); - - if (self.elements.count < 2) return; - - // Keep a running tab of how far the glyphs have traveled to - // be able to calculate the percent along the point path - float glyphDistance = 0.0f; - float lineLength = self.pathLength; - - for (int loc = 0; loc < string.length; loc++) - { - // Retrieve item - NSRange range = NSMakeRange(loc, 1); - NSAttributedString *item = [string attributedSubstringFromRange:range]; - - // Start halfway through each glyph - CGRect bounding = [item boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:0 context:nil]; - glyphDistance += bounding.size.width / 2; - - // Find point - CGPoint slope; - CGFloat percentConsumed = glyphDistance / lineLength; - CGPoint targetPoint = [self pointAtPercent:percentConsumed withSlope:&slope]; - - // Accommodate the forward progress - glyphDistance += bounding.size.width / 2; - if (percentConsumed >= 1.0f) break; - - // Calculate the rotation - float angle = atan(slope.y / slope.x); // + M_PI; - if (slope.x < 0) angle += M_PI; // going left, update the angle - - // Draw the glyph - PushDraw(^{ - CGContextTranslateCTM(context, targetPoint.x, targetPoint.y); - CGContextRotateCTM(context, angle); - CGContextTranslateCTM(context, -bounding.size.width / 2, -item.size.height / 2); - [item drawAtPoint:CGPointZero]; - }); - } -} -@end diff --git a/ios/QuartzBookPack/Utility/Utility.h b/ios/QuartzBookPack/Utility/Utility.h deleted file mode 100644 index 3ad23f58..00000000 --- a/ios/QuartzBookPack/Utility/Utility.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - - Erica Sadun, http://ericasadun.com - - */ - -#import -#import - -#import "BaseGeometry.h" -#import "Drawing-Block.h" -#import "Drawing-Util.h" -#import "Drawing-Gradient.h" -#import "Bezier.h" -#import "ImageUtils.h" -#import "UIBezierPath+Text.h" -#import "Drawing-Text.h" - -#define BARBUTTON(TITLE, SELECTOR) [[UIBarButtonItem alloc] initWithTitle:TITLE style:UIBarButtonItemStylePlain target:self action:SELECTOR] -#define RGBCOLOR(_R_, _G_, _B_) [UIColor colorWithRed:(CGFloat)(_R_)/255.0f green: (CGFloat)(_G_)/255.0f blue: (CGFloat)(_B_)/255.0f alpha: 1.0f] - -#define OLIVE RGBCOLOR(125, 162, 63) -#define LIGHTPURPLE RGBCOLOR(99, 62, 162) -#define DARKGREEN RGBCOLOR(40, 55, 32) - -// Bail with complaint -#define COMPLAIN_AND_BAIL(_COMPLAINT_, _ARG_) {NSLog(_COMPLAINT_, _ARG_); return;} -#define COMPLAIN_AND_BAIL_NIL(_COMPLAINT_, _ARG_) {NSLog(_COMPLAINT_, _ARG_); return nil;} - -#define SEED_RANDOM {static BOOL seeded = NO; if (!seeded) {seeded = YES; srandom((unsigned int) time(0));}} -#define RANDOM(_X_) (NSInteger)(random() % _X_) -#define RANDOM_01 ((double) random() / (double) LONG_MAX) -#define RANDOM_BOOL (BOOL)((NSInteger)random() % 2) -#define RANDOM_PT(_RECT_) CGPointMake(_RECT_.origin.x + RANDOM_01 * _RECT_.size.width, _RECT_.origin.y + RANDOM_01 * _RECT_.size.height) - -UIBezierPath *BuildBunnyPath(); -UIBezierPath *BuildMoofPath(); -UIBezierPath *BuildStarPath(); - -UIColor *NoiseColor(); - -@interface NSString (Utility) -+ (NSString *) lorem: (NSUInteger) numberOfParagraphs; -+ (NSString *) loremWords: (NSUInteger) numberOfWords; -@end - -#define DEBUG_IMAGE(_IMAGE_, _NAME_) [UIImagePNGRepresentation(_IMAGE_) writeToFile:[NSString stringWithFormat:@"/Users/ericasadun/Desktop/%@.png", _NAME_] atomically:YES] - diff --git a/ios/QuartzBookPack/Utility/Utility.m b/ios/QuartzBookPack/Utility/Utility.m deleted file mode 100644 index dacb2cc1..00000000 --- a/ios/QuartzBookPack/Utility/Utility.m +++ /dev/null @@ -1,240 +0,0 @@ -#import "Utility.h" - -typedef BOOL (^TestingBlock)(id object); -@interface NSArray (Utility) -@end - -@implementation NSArray (Utility) -- (NSArray *) collect: (TestingBlock) aBlock -{ - NSMutableArray *resultArray = [NSMutableArray array]; - for (id object in self) - { - BOOL result = aBlock(object); - if (result) - [resultArray addObject:object]; - } - return resultArray; -} -@end - -@implementation NSString (Utility) -+ (NSString *) ipsum:(NSUInteger) numberOfParagraphs -{ - NSString *urlString = [NSString stringWithFormat:@"http://loripsum.net/api/%0d/short/prude/plaintext", numberOfParagraphs]; - - NSError *error; - NSString *string = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSUTF8StringEncoding error:&error]; - if (!string) - { - NSLog(@"Error: %@", error.localizedDescription); - return nil; - } - return string; -} - -+ (NSString *) lorem:(NSUInteger) numberOfParagraphs -{ - return [self ipsum:numberOfParagraphs]; -} - -- (NSArray *) words -{ - NSArray *words = [self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - TestingBlock block = ^BOOL(id word){return [(NSString *)word length] > 0;}; - return [words collect:block]; -} - -- (NSString *) wordRange: (NSRange) range -{ - NSArray *componentWords = self.words; - NSInteger start = range.location; - NSInteger end = range.location + range.length; - if ((start >= componentWords.count) || (end >= componentWords.count)) - return nil; - - NSArray *subArray = [componentWords subarrayWithRange:range]; - return [subArray componentsJoinedByString:@" "]; -} - -+ (NSString *) loremWords: (NSUInteger) numberOfWords -{ - // meant for up to 10 words - NSUInteger nWords = MIN(numberOfWords, 10); - NSRange r = NSMakeRange(0, nWords); - return [[NSString lorem:3] wordRange:r]; -} -@end - -UIBezierPath *BuildBunnyPath() -{ - UIBezierPath *shapePath = [UIBezierPath bezierPath]; - [shapePath moveToPoint: CGPointMake(392.05, 150.53)]; - [shapePath addCurveToPoint: CGPointMake(343.11, 129.56) controlPoint1: CGPointMake(379.34, 133.37) controlPoint2: CGPointMake(359, 133.37)]; - [shapePath addCurveToPoint: CGPointMake(305.61, 71.72) controlPoint1: CGPointMake(341.2, 119.39) controlPoint2: CGPointMake(316.41, 71.08)]; - [shapePath addCurveToPoint: CGPointMake(304.34, 100.96) controlPoint1: CGPointMake(294.8, 72.35) controlPoint2: CGPointMake(302.43, 79.35)]; - [shapePath addCurveToPoint: CGPointMake(283.36, 84.43) controlPoint1: CGPointMake(299.25, 95.24) controlPoint2: CGPointMake(287.81, 73.63)]; - [shapePath addCurveToPoint: CGPointMake(301.79, 154.99) controlPoint1: CGPointMake(272.42, 111.01) controlPoint2: CGPointMake(302.43, 148.63)]; - [shapePath addCurveToPoint: CGPointMake(287.17, 191.85) controlPoint1: CGPointMake(301.16, 161.34) controlPoint2: CGPointMake(299, 186.78)]; - [shapePath addCurveToPoint: CGPointMake(194.38, 221.09) controlPoint1: CGPointMake(282.72, 193.76) controlPoint2: CGPointMake(240.78, 195.66)]; - [shapePath addCurveToPoint: CGPointMake(128.27, 320.25) controlPoint1: CGPointMake(147.97, 246.51) controlPoint2: CGPointMake(138.44, 282.11)]; - [shapePath addCurveToPoint: CGPointMake(124.75, 348.92) controlPoint1: CGPointMake(125.53, 330.51) controlPoint2: CGPointMake(124.54, 340.12)]; - [shapePath addCurveToPoint: CGPointMake(118.34, 358.13) controlPoint1: CGPointMake(122.92, 350.31) controlPoint2: CGPointMake(120.74, 353.02)]; - [shapePath addCurveToPoint: CGPointMake(136.06, 388.68) controlPoint1: CGPointMake(112.42, 370.73) controlPoint2: CGPointMake(123.06, 383.91)]; - [shapePath addCurveToPoint: CGPointMake(144.8, 399.06) controlPoint1: CGPointMake(138.8, 392.96) controlPoint2: CGPointMake(141.79, 396.49)]; - [shapePath addCurveToPoint: CGPointMake(210.9, 408.6) controlPoint1: CGPointMake(158.14, 410.5) controlPoint2: CGPointMake(205.18, 406.69)]; - [shapePath addCurveToPoint: CGPointMake(240.78, 417.5) controlPoint1: CGPointMake(216.62, 410.5) controlPoint2: CGPointMake(234.41, 417.5)]; - [shapePath addCurveToPoint: CGPointMake(267.47, 411.78) controlPoint1: CGPointMake(247.13, 417.5) controlPoint2: CGPointMake(267.47, 419.4)]; - [shapePath addCurveToPoint: CGPointMake(250.3, 385.71) controlPoint1: CGPointMake(267.47, 394.61) controlPoint2: CGPointMake(250.3, 385.71)]; - [shapePath addCurveToPoint: CGPointMake(274.46, 371.73) controlPoint1: CGPointMake(250.3, 385.71) controlPoint2: CGPointMake(260.48, 379.99)]; - [shapePath addCurveToPoint: CGPointMake(302.43, 350.12) controlPoint1: CGPointMake(288.45, 363.47) controlPoint2: CGPointMake(297.34, 350.76)]; - [shapePath addCurveToPoint: CGPointMake(318.32, 389.53) controlPoint1: CGPointMake(312.22, 348.89) controlPoint2: CGPointMake(311.33, 381.9)]; - [shapePath addCurveToPoint: CGPointMake(341.84, 421.94) controlPoint1: CGPointMake(325.32, 397.15) controlPoint2: CGPointMake(332.15, 418.51)]; - [shapePath addCurveToPoint: CGPointMake(375.53, 413.68) controlPoint1: CGPointMake(349.08, 424.51) controlPoint2: CGPointMake(373.62, 421.31)]; - [shapePath addCurveToPoint: CGPointMake(367.26, 398.43) controlPoint1: CGPointMake(377.43, 406.06) controlPoint2: CGPointMake(372.35, 405.42)]; - [shapePath addCurveToPoint: CGPointMake(361.54, 352.66) controlPoint1: CGPointMake(362.18, 391.43) controlPoint2: CGPointMake(356.46, 363.47)]; - [shapePath addCurveToPoint: CGPointMake(378.07, 277.66) controlPoint1: CGPointMake(366.63, 341.86) controlPoint2: CGPointMake(376.8, 296.73)]; - [shapePath addCurveToPoint: CGPointMake(388.87, 220.45) controlPoint1: CGPointMake(379.34, 258.59) controlPoint2: CGPointMake(378.7, 245.88)]; - [shapePath addCurveToPoint: CGPointMake(411.12, 189.31) controlPoint1: CGPointMake(405.4, 214.1) controlPoint2: CGPointMake(410.48, 197.57)]; - [shapePath addCurveToPoint: CGPointMake(392.05, 150.53) controlPoint1: CGPointMake(411.76, 181.04) controlPoint2: CGPointMake(404.76, 167.7)]; - [shapePath closePath]; - return shapePath; -} - -// http://pastie.org/private/7i0lgpfqtlkihbjyn0ba -// http://imgur.com/Po3uoIy -UIBezierPath *BuildMoofPath() -{ - UIBezierPath *path = [UIBezierPath bezierPath]; - [path moveToPoint: CGPointMake(107, 66)]; - [path addCurveToPoint: CGPointMake(119, 69) controlPoint1: CGPointMake(113.17, 65.65) controlPoint2: CGPointMake(116.61, 65.38)]; - [path addCurveToPoint: CGPointMake(118, 100) controlPoint1: CGPointMake(118.67, 79.33) controlPoint2: CGPointMake(118.33, 89.67)]; - [path addCurveToPoint: CGPointMake(140, 114) controlPoint1: CGPointMake(125.33, 104.67) controlPoint2: CGPointMake(132.67, 109.33)]; - [path addCurveToPoint: CGPointMake(240, 105) controlPoint1: CGPointMake(169.22, 124.94) controlPoint2: CGPointMake(219.91, 117.23)]; - [path addCurveToPoint: CGPointMake(261, 76) controlPoint1: CGPointMake(252.29, 97.52) controlPoint2: CGPointMake(251.99, 86.39)]; - [path addCurveToPoint: CGPointMake(267, 78) controlPoint1: CGPointMake(263, 76.67) controlPoint2: CGPointMake(265, 77.33)]; - [path addCurveToPoint: CGPointMake(255, 145) controlPoint1: CGPointMake(276.45, 112.7) controlPoint2: CGPointMake(260.16, 119.11)]; - [path addCurveToPoint: CGPointMake(262, 188) controlPoint1: CGPointMake(257.33, 159.33) controlPoint2: CGPointMake(259.67, 173.67)]; - [path addCurveToPoint: CGPointMake(208, 232) controlPoint1: CGPointMake(268.07, 224.31) controlPoint2: CGPointMake(240.23, 239.3)]; - [path addCurveToPoint: CGPointMake(206, 225) controlPoint1: CGPointMake(207.33, 229.67) controlPoint2: CGPointMake(206.67, 227.33)]; - [path addCurveToPoint: CGPointMake(220, 192) controlPoint1: CGPointMake(217.21, 215.24) controlPoint2: CGPointMake(226.39, 211.63)]; - [path addCurveToPoint: CGPointMake(127, 186) controlPoint1: CGPointMake(197.32, 181.14) controlPoint2: CGPointMake(155.61, 179.26)]; - [path addCurveToPoint: CGPointMake(78, 230) controlPoint1: CGPointMake(126.93, 214.62) controlPoint2: CGPointMake(110.79, 250.16)]; - [path addCurveToPoint: CGPointMake(86, 203) controlPoint1: CGPointMake(76.79, 220.05) controlPoint2: CGPointMake(83.57, 212.84)]; - [path addCurveToPoint: CGPointMake(85, 132) controlPoint1: CGPointMake(90.93, 183.08) controlPoint2: CGPointMake(90.79, 150.81)]; - [path addCurveToPoint: CGPointMake(28, 121) controlPoint1: CGPointMake(60.95, 132.68) controlPoint2: CGPointMake(39.36, 132.88)]; - [path addCurveToPoint: CGPointMake(57, 91) controlPoint1: CGPointMake(27.34, 95.81) controlPoint2: CGPointMake(48.07, 104.89)]; - [path addCurveToPoint: CGPointMake(60, 73) controlPoint1: CGPointMake(58, 85) controlPoint2: CGPointMake(59, 79)]; - [path addCurveToPoint: CGPointMake(85, 76) controlPoint1: CGPointMake(66.31, 61.96) controlPoint2: CGPointMake(80.38, 68.36)]; - [path addCurveToPoint: CGPointMake(107, 66) controlPoint1: CGPointMake(93.79, 75.13) controlPoint2: CGPointMake(101.6, 70.61)]; - [path closePath]; - [path moveToPoint: CGPointMake(116, 69)]; - [path addCurveToPoint: CGPointMake(84, 78) controlPoint1: CGPointMake(104.12, 69.8) controlPoint2: CGPointMake(92.62, 83.34)]; - [path addCurveToPoint: CGPointMake(77, 72) controlPoint1: CGPointMake(81.67, 76) controlPoint2: CGPointMake(79.33, 74)]; - [path addCurveToPoint: CGPointMake(67, 72) controlPoint1: CGPointMake(73.67, 72) controlPoint2: CGPointMake(70.33, 72)]; - [path addCurveToPoint: CGPointMake(60, 93) controlPoint1: CGPointMake(60.55, 76.74) controlPoint2: CGPointMake(64.31, 86.1)]; - [path addCurveToPoint: CGPointMake(32, 111) controlPoint1: CGPointMake(54.17, 102.33) controlPoint2: CGPointMake(37.4, 101.45)]; - [path addCurveToPoint: CGPointMake(32, 121) controlPoint1: CGPointMake(32, 114.33) controlPoint2: CGPointMake(32, 117.67)]; - [path addCurveToPoint: CGPointMake(88, 129) controlPoint1: CGPointMake(44.53, 129.24) controlPoint2: CGPointMake(66.88, 129.21)]; - [path addCurveToPoint: CGPointMake(109, 172) controlPoint1: CGPointMake(93.2, 149.04) controlPoint2: CGPointMake(120.58, 148.18)]; - [path addCurveToPoint: CGPointMake(92, 176) controlPoint1: CGPointMake(103.33, 173.33) controlPoint2: CGPointMake(97.67, 174.67)]; - [path addCurveToPoint: CGPointMake(83, 230) controlPoint1: CGPointMake(91.91, 195.18) controlPoint2: CGPointMake(78.84, 222.44)]; - [path addCurveToPoint: CGPointMake(85, 230) controlPoint1: CGPointMake(83.67, 230) controlPoint2: CGPointMake(84.33, 230)]; - [path addCurveToPoint: CGPointMake(127, 183) controlPoint1: CGPointMake(131.62, 242.71) controlPoint2: CGPointMake(110.92, 195.36)]; - [path addCurveToPoint: CGPointMake(223, 190) controlPoint1: CGPointMake(149.67, 169.94) controlPoint2: CGPointMake(207.14, 180.38)]; - [path addCurveToPoint: CGPointMake(209, 226) controlPoint1: CGPointMake(228.64, 206.57) controlPoint2: CGPointMake(224.64, 221.84)]; - [path addCurveToPoint: CGPointMake(210, 229) controlPoint1: CGPointMake(209.33, 227) controlPoint2: CGPointMake(209.67, 228)]; - [path addCurveToPoint: CGPointMake(258, 184) controlPoint1: CGPointMake(240.81, 233.96) controlPoint2: CGPointMake(265.07, 221.63)]; - [path addCurveToPoint: CGPointMake(251, 147) controlPoint1: CGPointMake(255.67, 171.67) controlPoint2: CGPointMake(253.33, 159.33)]; - [path addCurveToPoint: CGPointMake(262, 79) controlPoint1: CGPointMake(253.73, 128.51) controlPoint2: CGPointMake(281.22, 99.39)]; - [path addCurveToPoint: CGPointMake(230, 113) controlPoint1: CGPointMake(260.12, 98.13) controlPoint2: CGPointMake(245.13, 107.06)]; - [path addCurveToPoint: CGPointMake(174, 146) controlPoint1: CGPointMake(229.65, 133.05) controlPoint2: CGPointMake(198.37, 155.24)]; - [path addCurveToPoint: CGPointMake(150, 119) controlPoint1: CGPointMake(166, 137) controlPoint2: CGPointMake(158, 128)]; - [path addCurveToPoint: CGPointMake(101, 96) controlPoint1: CGPointMake(138.77, 111.56) controlPoint2: CGPointMake(109.21, 105.11)]; - [path addCurveToPoint: CGPointMake(116, 69) controlPoint1: CGPointMake(103.48, 82.21) controlPoint2: CGPointMake(113.99, 82.77)]; - [path closePath]; - [path moveToPoint: CGPointMake(76, 93)]; - [path addCurveToPoint: CGPointMake(82, 93) controlPoint1: CGPointMake(78, 93) controlPoint2: CGPointMake(80, 93)]; - [path addCurveToPoint: CGPointMake(82, 98) controlPoint1: CGPointMake(82, 94.67) controlPoint2: CGPointMake(82, 96.33)]; - [path addCurveToPoint: CGPointMake(76, 98) controlPoint1: CGPointMake(80, 98) controlPoint2: CGPointMake(78, 98)]; - [path addCurveToPoint: CGPointMake(76, 93) controlPoint1: CGPointMake(76, 96.33) controlPoint2: CGPointMake(76, 94.67)]; - [path closePath]; - return path; -} - -UIBezierPath *BuildStarPath() -{ - // Create new path, courtesy of PaintCode (paintcodeapp.com) - UIBezierPath* bezierPath = [UIBezierPath bezierPath]; - - // Move to the start of the path - [bezierPath moveToPoint: CGPointMake(883.23, 430.54)]; - - // Add the cubic segments - [bezierPath addCurveToPoint: CGPointMake(749.25, 358.4) - controlPoint1: CGPointMake(873.68, 370.91) - controlPoint2: CGPointMake(809.43, 367.95)]; - [bezierPath addCurveToPoint: CGPointMake(668.1, 353.25) - controlPoint1: CGPointMake(721.92, 354.07) - controlPoint2: CGPointMake(690.4, 362.15)]; - [bezierPath addCurveToPoint: CGPointMake(492.9, 156.15) - controlPoint1: CGPointMake(575.39, 316.25) - controlPoint2: CGPointMake(629.21, 155.47)]; - [bezierPath addCurveToPoint: CGPointMake(461.98, 169.03) - controlPoint1: CGPointMake(482.59, 160.45) - controlPoint2: CGPointMake(472.29, 164.74)]; - [bezierPath addCurveToPoint: CGPointMake(365.36, 345.52) - controlPoint1: CGPointMake(409.88, 207.98) - controlPoint2: CGPointMake(415.22, 305.32)]; - [bezierPath addCurveToPoint: CGPointMake(262.31, 358.4) - controlPoint1: CGPointMake(341.9, 364.44) - controlPoint2: CGPointMake(300.41, 352.37)]; - [bezierPath addCurveToPoint: CGPointMake(133.48, 460.17) - controlPoint1: CGPointMake(200.89, 368.12) - controlPoint2: CGPointMake(118.62, 376.61)]; - [bezierPath addCurveToPoint: CGPointMake(277.77, 622.49) - controlPoint1: CGPointMake(148.46, 544.36) - controlPoint2: CGPointMake(258.55, 560.05)]; - [bezierPath addCurveToPoint: CGPointMake(277.77, 871.12) - controlPoint1: CGPointMake(301.89, 700.9) - controlPoint2: CGPointMake(193.24, 819.76)]; - [bezierPath addCurveToPoint: CGPointMake(513.51, 798.97) - controlPoint1: CGPointMake(382.76, 934.9) - controlPoint2: CGPointMake(435.24, 786.06)]; - [bezierPath addCurveToPoint: CGPointMake(723.49, 878.84) - controlPoint1: CGPointMake(582.42, 810.35) - controlPoint2: CGPointMake(628.93, 907.89)]; - [bezierPath addCurveToPoint: CGPointMake(740.24, 628.93) - controlPoint1: CGPointMake(834.7, 844.69) - controlPoint2: CGPointMake(722.44, 699.2)]; - [bezierPath addCurveToPoint: CGPointMake(883.23, 430.54) - controlPoint1: CGPointMake(756.58, 564.39) - controlPoint2: CGPointMake(899.19, 530.23)]; - - // Close the path. It’s now ready to draw - [bezierPath closePath]; - return bezierPath; -} - -UIColor *NoiseColor() -{ - static UIImage *noise = nil; - if (noise) - return [UIColor colorWithPatternImage:noise]; - - srandom(time(0)); - - CGSize size = CGSizeMake(128, 128); - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - for (int j = 0; j < size.height; j++) - for (int i = 0; i < size.height; i++) - { - UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(i, j, 1, 1)]; - CGFloat level = ((double) random() / (double) LONG_MAX); - [path fill:[UIColor colorWithWhite:level alpha:1]]; - } - noise = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return [UIColor colorWithPatternImage:noise]; -} diff --git a/ios/RNSVG.xcodeproj/project.pbxproj b/ios/RNSVG.xcodeproj/project.pbxproj index 8157a368..6fa3e164 100644 --- a/ios/RNSVG.xcodeproj/project.pbxproj +++ b/ios/RNSVG.xcodeproj/project.pbxproj @@ -53,18 +53,6 @@ 7FC260CE1E3499BC00A39833 /* RNSVGViewBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260CD1E3499BC00A39833 /* RNSVGViewBox.m */; }; 7FC260D11E34A12000A39833 /* RNSVGSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260D01E34A12000A39833 /* RNSVGSymbol.m */; }; 7FC260D41E34A12A00A39833 /* RNSVGSymbolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260D31E34A12A00A39833 /* RNSVGSymbolManager.m */; }; - 945A8AE11F4CBFD1004BBF6B /* Drawing-Text.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8ADF1F4CBFD1004BBF6B /* Drawing-Text.m */; }; - 945A8AE21F4CBFD1004BBF6B /* UIBezierPath+Text.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AE01F4CBFD1004BBF6B /* UIBezierPath+Text.m */; }; - 945A8AE41F4CC01D004BBF6B /* UIBezierPath+Elements.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AE31F4CC01D004BBF6B /* UIBezierPath+Elements.m */; }; - 945A8AE61F4CC037004BBF6B /* BaseGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AE51F4CC037004BBF6B /* BaseGeometry.m */; }; - 945A8AE81F4CC04C004BBF6B /* BezierUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AE71F4CC04C004BBF6B /* BezierUtils.m */; }; - 945A8AEA1F4CC050004BBF6B /* BezierFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AE91F4CC050004BBF6B /* BezierFunctions.m */; }; - 945A8AEC1F4CC055004BBF6B /* BezierElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AEB1F4CC055004BBF6B /* BezierElement.m */; }; - 945A8AEE1F4CC07A004BBF6B /* Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AED1F4CC07A004BBF6B /* Utility.m */; }; - 945A8AF01F4CC092004BBF6B /* Drawing-Block.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AEF1F4CC092004BBF6B /* Drawing-Block.m */; }; - 945A8AF31F4CC0AF004BBF6B /* Drawing-Gradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AF11F4CC0AF004BBF6B /* Drawing-Gradient.m */; }; - 945A8AF41F4CC0AF004BBF6B /* Drawing-Util.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AF21F4CC0AF004BBF6B /* Drawing-Util.m */; }; - 945A8AF61F4CC0C1004BBF6B /* ImageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AF51F4CC0C1004BBF6B /* ImageUtils.m */; }; 945A8AF81F4CE3E8004BBF6B /* AlignmentBaseline.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AF71F4CE3E8004BBF6B /* AlignmentBaseline.m */; }; 945A8AF91F4CE3E8004BBF6B /* AlignmentBaseline.m in Sources */ = {isa = PBXBuildFile; fileRef = 945A8AF71F4CE3E8004BBF6B /* AlignmentBaseline.m */; }; 9494C47A1F47116800D5BCFD /* PerformanceBezier.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9494C4771F4710FE00D5BCFD /* PerformanceBezier.framework */; }; @@ -288,18 +276,6 @@ 7FC260D21E34A12A00A39833 /* RNSVGSymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGSymbolManager.h; sourceTree = ""; }; 7FC260D31E34A12A00A39833 /* RNSVGSymbolManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGSymbolManager.m; sourceTree = ""; }; 945A8ADD1F4CB7F9004BBF6B /* QuartzBookPack */ = {isa = PBXFileReference; lastKnownFileType = folder; path = QuartzBookPack; sourceTree = ""; }; - 945A8ADF1F4CBFD1004BBF6B /* Drawing-Text.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Drawing-Text.m"; path = "QuartzBookPack/TextDrawing/Drawing-Text.m"; sourceTree = ""; }; - 945A8AE01F4CBFD1004BBF6B /* UIBezierPath+Text.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIBezierPath+Text.m"; path = "QuartzBookPack/TextDrawing/UIBezierPath+Text.m"; sourceTree = ""; }; - 945A8AE31F4CC01D004BBF6B /* UIBezierPath+Elements.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIBezierPath+Elements.m"; path = "QuartzBookPack/Bezier/UIBezierPath+Elements.m"; sourceTree = ""; }; - 945A8AE51F4CC037004BBF6B /* BaseGeometry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BaseGeometry.m; path = QuartzBookPack/Geometry/BaseGeometry.m; sourceTree = ""; }; - 945A8AE71F4CC04C004BBF6B /* BezierUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BezierUtils.m; path = QuartzBookPack/Bezier/BezierUtils.m; sourceTree = ""; }; - 945A8AE91F4CC050004BBF6B /* BezierFunctions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BezierFunctions.m; path = QuartzBookPack/Bezier/BezierFunctions.m; sourceTree = ""; }; - 945A8AEB1F4CC055004BBF6B /* BezierElement.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BezierElement.m; path = QuartzBookPack/Bezier/BezierElement.m; sourceTree = ""; }; - 945A8AED1F4CC07A004BBF6B /* Utility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Utility.m; path = QuartzBookPack/Utility/Utility.m; sourceTree = ""; }; - 945A8AEF1F4CC092004BBF6B /* Drawing-Block.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Drawing-Block.m"; path = "QuartzBookPack/Drawing/Drawing-Block.m"; sourceTree = ""; }; - 945A8AF11F4CC0AF004BBF6B /* Drawing-Gradient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Drawing-Gradient.m"; path = "QuartzBookPack/Drawing/Drawing-Gradient.m"; sourceTree = ""; }; - 945A8AF21F4CC0AF004BBF6B /* Drawing-Util.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Drawing-Util.m"; path = "QuartzBookPack/Drawing/Drawing-Util.m"; sourceTree = ""; }; - 945A8AF51F4CC0C1004BBF6B /* ImageUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ImageUtils.m; path = QuartzBookPack/Image/ImageUtils.m; sourceTree = ""; }; 945A8AF71F4CE3E8004BBF6B /* AlignmentBaseline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AlignmentBaseline.m; path = Text/AlignmentBaseline.m; sourceTree = ""; }; 945A8AFA1F4CE41E004BBF6B /* AlignmentBaseline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AlignmentBaseline.h; path = Text/AlignmentBaseline.h; sourceTree = ""; }; 9494C4711F4710FE00D5BCFD /* PerformanceBezier.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PerformanceBezier.xcodeproj; path = PerformanceBezier/PerformanceBezier.xcodeproj; sourceTree = ""; }; @@ -366,18 +342,6 @@ 0CF68AB81AF0540F00FF9E5C = { isa = PBXGroup; children = ( - 945A8AF51F4CC0C1004BBF6B /* ImageUtils.m */, - 945A8AF11F4CC0AF004BBF6B /* Drawing-Gradient.m */, - 945A8AF21F4CC0AF004BBF6B /* Drawing-Util.m */, - 945A8AEF1F4CC092004BBF6B /* Drawing-Block.m */, - 945A8AED1F4CC07A004BBF6B /* Utility.m */, - 945A8AEB1F4CC055004BBF6B /* BezierElement.m */, - 945A8AE91F4CC050004BBF6B /* BezierFunctions.m */, - 945A8AE71F4CC04C004BBF6B /* BezierUtils.m */, - 945A8AE51F4CC037004BBF6B /* BaseGeometry.m */, - 945A8AE31F4CC01D004BBF6B /* UIBezierPath+Elements.m */, - 945A8ADF1F4CBFD1004BBF6B /* Drawing-Text.m */, - 945A8AE01F4CBFD1004BBF6B /* UIBezierPath+Text.m */, 945A8ADD1F4CB7F9004BBF6B /* QuartzBookPack */, 9494C4711F4710FE00D5BCFD /* PerformanceBezier.xcodeproj */, 1039D29A1CE7212C001E90A8 /* Utils */, @@ -687,18 +651,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 945A8AF01F4CC092004BBF6B /* Drawing-Block.m in Sources */, - 945A8AF31F4CC0AF004BBF6B /* Drawing-Gradient.m in Sources */, - 945A8AF41F4CC0AF004BBF6B /* Drawing-Util.m in Sources */, - 945A8AF61F4CC0C1004BBF6B /* ImageUtils.m in Sources */, - 945A8AEE1F4CC07A004BBF6B /* Utility.m in Sources */, - 945A8AE81F4CC04C004BBF6B /* BezierUtils.m in Sources */, - 945A8AEC1F4CC055004BBF6B /* BezierElement.m in Sources */, - 945A8AEA1F4CC050004BBF6B /* BezierFunctions.m in Sources */, - 945A8AE61F4CC037004BBF6B /* BaseGeometry.m in Sources */, - 945A8AE41F4CC01D004BBF6B /* UIBezierPath+Elements.m in Sources */, - 945A8AE11F4CBFD1004BBF6B /* Drawing-Text.m in Sources */, - 945A8AE21F4CBFD1004BBF6B /* UIBezierPath+Text.m in Sources */, 10BA0D3F1CE74E3100887C2B /* RNSVGTextManager.m in Sources */, 1039D28A1CE71EB7001E90A8 /* RNSVGImage.m in Sources */, 10BA0D4B1CE74E3D00887C2B /* RNSVGRect.m in Sources */, diff --git a/package.json b/package.json index 760c9d1d..71360650 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "6.0.0-rc1", + "version": "6.0.0-rc10", "name": "react-native-svg", "description": "SVG library for react-native", "repository": { @@ -19,7 +19,8 @@ "gradient" ], "scripts": { - "lint": "eslint ./" + "lint": "eslint ./", + "postinstall" : "node scripts/install.js" }, "peerDependencies": { "react-native": ">=0.50.0", @@ -28,7 +29,8 @@ }, "dependencies": { "color": "^0.11.1", - "lodash": "^4.16.6" + "lodash": "^4.16.6", + "github-download": "^0.5.0" }, "devDependencies": { "babel-eslint": "^6.1.2", diff --git a/scripts/install.js b/scripts/install.js new file mode 100644 index 00000000..379fa89a --- /dev/null +++ b/scripts/install.js @@ -0,0 +1,20 @@ +var path = require('path'); +var ghdownload = require('github-download'); + +function downloadSubModuleFromGithub(user, repo, callback) { + var dist = path.join(process.cwd(), 'ios/' + repo); + + console.log('\r\n Start downloading ' + repo + ' to `' + dist + '`'); + ghdownload({user: user, repo: repo, ref: 'master'}, dist) + .on('end', function() { + console.log('Download ' + repo + ' library success!'); + callback && callback(); + }) + .on('error', function (err) { + console.error('Download ' + repo + ' library from github failed with err:', err); + }); +} + +downloadSubModuleFromGithub('adamwulf', 'PerformanceBezier', function () { + downloadSubModuleFromGithub('magicismight', 'QuartzBookPack'); +});