123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- //
- // YYCGUtilities.m
- // YYKit <https://github.com/ibireme/YYKit>
- //
- // Created by ibireme on 15/2/28.
- // Copyright (c) 2015 ibireme.
- //
- // This source code is licensed under the MIT-style license found in the
- // LICENSE file in the root directory of this source tree.
- //
- #import "YYCGUtilities.h"
- #import <Accelerate/Accelerate.h>
- #import "UIView+YYAdd.h"
- CGContextRef YYCGContextCreateARGBBitmapContext(CGSize size, BOOL opaque, CGFloat scale) {
- size_t width = ceil(size.width * scale);
- size_t height = ceil(size.height * scale);
- if (width < 1 || height < 1) return NULL;
-
- //pre-multiplied ARGB, 8-bits per component
- CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
- CGImageAlphaInfo alphaInfo = (opaque ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaPremultipliedFirst);
- CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, kCGBitmapByteOrderDefault | alphaInfo);
- CGColorSpaceRelease(space);
- if (context) {
- CGContextTranslateCTM(context, 0, height);
- CGContextScaleCTM(context, scale, -scale);
- }
- return context;
- }
- CGContextRef YYCGContextCreateGrayBitmapContext(CGSize size, CGFloat scale) {
- size_t width = ceil(size.width * scale);
- size_t height = ceil(size.height * scale);
- if (width < 1 || height < 1) return NULL;
-
- //DeviceGray, 8-bits per component
- CGColorSpaceRef space = CGColorSpaceCreateDeviceGray();
- CGImageAlphaInfo alphaInfo = kCGImageAlphaNone;
- CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, kCGBitmapByteOrderDefault | alphaInfo);
- CGColorSpaceRelease(space);
- if (context) {
- CGContextTranslateCTM(context, 0, height);
- CGContextScaleCTM(context, scale, -scale);
- }
- return context;
- }
- CGFloat YYScreenScale() {
- static CGFloat scale;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- scale = [UIScreen mainScreen].scale;
- });
- return scale;
- }
- CGSize YYScreenSize() {
- static CGSize size;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- size = [UIScreen mainScreen].bounds.size;
- if (size.height < size.width) {
- CGFloat tmp = size.height;
- size.height = size.width;
- size.width = tmp;
- }
- });
- return size;
- }
- // return 0 when succeed
- static int matrix_invert(__CLPK_integer N, double *matrix) {
- __CLPK_integer error = 0;
- __CLPK_integer pivot_tmp[6 * 6];
- __CLPK_integer *pivot = pivot_tmp;
- double workspace_tmp[6 * 6];
- double *workspace = workspace_tmp;
- bool need_free = false;
-
- if (N > 6) {
- need_free = true;
- pivot = malloc(N * N * sizeof(__CLPK_integer));
- if (!pivot) return -1;
- workspace = malloc(N * sizeof(double));
- if (!workspace) {
- free(pivot);
- return -1;
- }
- }
-
- dgetrf_(&N, &N, matrix, &N, pivot, &error);
-
- if (error == 0) {
- dgetri_(&N, matrix, &N, pivot, workspace, &N, &error);
- }
-
- if (need_free) {
- free(pivot);
- free(workspace);
- }
- return error;
- }
- CGAffineTransform YYCGAffineTransformGetFromPoints(CGPoint before[3], CGPoint after[3]) {
- if (before == NULL || after == NULL) return CGAffineTransformIdentity;
-
- CGPoint p1, p2, p3, q1, q2, q3;
- p1 = before[0]; p2 = before[1]; p3 = before[2];
- q1 = after[0]; q2 = after[1]; q3 = after[2];
-
- double A[36];
- A[ 0] = p1.x; A[ 1] = p1.y; A[ 2] = 0; A[ 3] = 0; A[ 4] = 1; A[ 5] = 0;
- A[ 6] = 0; A[ 7] = 0; A[ 8] = p1.x; A[ 9] = p1.y; A[10] = 0; A[11] = 1;
- A[12] = p2.x; A[13] = p2.y; A[14] = 0; A[15] = 0; A[16] = 1; A[17] = 0;
- A[18] = 0; A[19] = 0; A[20] = p2.x; A[21] = p2.y; A[22] = 0; A[23] = 1;
- A[24] = p3.x; A[25] = p3.y; A[26] = 0; A[27] = 0; A[28] = 1; A[29] = 0;
- A[30] = 0; A[31] = 0; A[32] = p3.x; A[33] = p3.y; A[34] = 0; A[35] = 1;
-
- int error = matrix_invert(6, A);
- if (error) return CGAffineTransformIdentity;
-
- double B[6];
- B[0] = q1.x; B[1] = q1.y; B[2] = q2.x; B[3] = q2.y; B[4] = q3.x; B[5] = q3.y;
-
- double M[6];
- M[0] = A[ 0] * B[0] + A[ 1] * B[1] + A[ 2] * B[2] + A[ 3] * B[3] + A[ 4] * B[4] + A[ 5] * B[5];
- M[1] = A[ 6] * B[0] + A[ 7] * B[1] + A[ 8] * B[2] + A[ 9] * B[3] + A[10] * B[4] + A[11] * B[5];
- M[2] = A[12] * B[0] + A[13] * B[1] + A[14] * B[2] + A[15] * B[3] + A[16] * B[4] + A[17] * B[5];
- M[3] = A[18] * B[0] + A[19] * B[1] + A[20] * B[2] + A[21] * B[3] + A[22] * B[4] + A[23] * B[5];
- M[4] = A[24] * B[0] + A[25] * B[1] + A[26] * B[2] + A[27] * B[3] + A[28] * B[4] + A[29] * B[5];
- M[5] = A[30] * B[0] + A[31] * B[1] + A[32] * B[2] + A[33] * B[3] + A[34] * B[4] + A[35] * B[5];
-
- CGAffineTransform transform = CGAffineTransformMake(M[0], M[2], M[1], M[3], M[4], M[5]);
- return transform;
- }
- CGAffineTransform YYCGAffineTransformGetFromViews(UIView *from, UIView *to) {
- if (!from || !to) return CGAffineTransformIdentity;
-
- CGPoint before[3], after[3];
- before[0] = CGPointMake(0, 0);
- before[1] = CGPointMake(0, 1);
- before[2] = CGPointMake(1, 0);
- after[0] = [from convertPoint:before[0] toViewOrWindow:to];
- after[1] = [from convertPoint:before[1] toViewOrWindow:to];
- after[2] = [from convertPoint:before[2] toViewOrWindow:to];
-
- return YYCGAffineTransformGetFromPoints(before, after);
- }
- UIViewContentMode YYCAGravityToUIViewContentMode(NSString *gravity) {
- static NSDictionary *dic;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- dic = @{ kCAGravityCenter:@(UIViewContentModeCenter),
- kCAGravityTop:@(UIViewContentModeTop),
- kCAGravityBottom:@(UIViewContentModeBottom),
- kCAGravityLeft:@(UIViewContentModeLeft),
- kCAGravityRight:@(UIViewContentModeRight),
- kCAGravityTopLeft:@(UIViewContentModeTopLeft),
- kCAGravityTopRight:@(UIViewContentModeTopRight),
- kCAGravityBottomLeft:@(UIViewContentModeBottomLeft),
- kCAGravityBottomRight:@(UIViewContentModeBottomRight),
- kCAGravityResize:@(UIViewContentModeScaleToFill),
- kCAGravityResizeAspect:@(UIViewContentModeScaleAspectFit),
- kCAGravityResizeAspectFill:@(UIViewContentModeScaleAspectFill) };
- });
- if (!gravity) return UIViewContentModeScaleToFill;
- return (UIViewContentMode)((NSNumber *)dic[gravity]).integerValue;
- }
- NSString *YYUIViewContentModeToCAGravity(UIViewContentMode contentMode) {
- switch (contentMode) {
- case UIViewContentModeScaleToFill: return kCAGravityResize;
- case UIViewContentModeScaleAspectFit: return kCAGravityResizeAspect;
- case UIViewContentModeScaleAspectFill: return kCAGravityResizeAspectFill;
- case UIViewContentModeRedraw: return kCAGravityResize;
- case UIViewContentModeCenter: return kCAGravityCenter;
- case UIViewContentModeTop: return kCAGravityTop;
- case UIViewContentModeBottom: return kCAGravityBottom;
- case UIViewContentModeLeft: return kCAGravityLeft;
- case UIViewContentModeRight: return kCAGravityRight;
- case UIViewContentModeTopLeft: return kCAGravityTopLeft;
- case UIViewContentModeTopRight: return kCAGravityTopRight;
- case UIViewContentModeBottomLeft: return kCAGravityBottomLeft;
- case UIViewContentModeBottomRight: return kCAGravityBottomRight;
- default: return kCAGravityResize;
- }
- }
- CGRect YYCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode) {
- rect = CGRectStandardize(rect);
- size.width = size.width < 0 ? -size.width : size.width;
- size.height = size.height < 0 ? -size.height : size.height;
- CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
- switch (mode) {
- case UIViewContentModeScaleAspectFit:
- case UIViewContentModeScaleAspectFill: {
- if (rect.size.width < 0.01 || rect.size.height < 0.01 ||
- size.width < 0.01 || size.height < 0.01) {
- rect.origin = center;
- rect.size = CGSizeZero;
- } else {
- CGFloat scale;
- if (mode == UIViewContentModeScaleAspectFit) {
- if (size.width / size.height < rect.size.width / rect.size.height) {
- scale = rect.size.height / size.height;
- } else {
- scale = rect.size.width / size.width;
- }
- } else {
- if (size.width / size.height < rect.size.width / rect.size.height) {
- scale = rect.size.width / size.width;
- } else {
- scale = rect.size.height / size.height;
- }
- }
- size.width *= scale;
- size.height *= scale;
- rect.size = size;
- rect.origin = CGPointMake(center.x - size.width * 0.5, center.y - size.height * 0.5);
- }
- } break;
- case UIViewContentModeCenter: {
- rect.size = size;
- rect.origin = CGPointMake(center.x - size.width * 0.5, center.y - size.height * 0.5);
- } break;
- case UIViewContentModeTop: {
- rect.origin.x = center.x - size.width * 0.5;
- rect.size = size;
- } break;
- case UIViewContentModeBottom: {
- rect.origin.x = center.x - size.width * 0.5;
- rect.origin.y += rect.size.height - size.height;
- rect.size = size;
- } break;
- case UIViewContentModeLeft: {
- rect.origin.y = center.y - size.height * 0.5;
- rect.size = size;
- } break;
- case UIViewContentModeRight: {
- rect.origin.y = center.y - size.height * 0.5;
- rect.origin.x += rect.size.width - size.width;
- rect.size = size;
- } break;
- case UIViewContentModeTopLeft: {
- rect.size = size;
- } break;
- case UIViewContentModeTopRight: {
- rect.origin.x += rect.size.width - size.width;
- rect.size = size;
- } break;
- case UIViewContentModeBottomLeft: {
- rect.origin.y += rect.size.height - size.height;
- rect.size = size;
- } break;
- case UIViewContentModeBottomRight: {
- rect.origin.x += rect.size.width - size.width;
- rect.origin.y += rect.size.height - size.height;
- rect.size = size;
- } break;
- case UIViewContentModeScaleToFill:
- case UIViewContentModeRedraw:
- default: {
- rect = rect;
- }
- }
- return rect;
- }
|