123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //
- // YYCGUtilities.h
- // 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 <UIKit/UIKit.h>
- #import <QuartzCore/QuartzCore.h>
- #if __has_include(<YYKit/YYKit.h>)
- #import <YYKit/YYKitMacro.h>
- #else
- #import "YYKitMacro.h"
- #endif
- YY_EXTERN_C_BEGIN
- NS_ASSUME_NONNULL_BEGIN
- /// Create an `ARGB` Bitmap context. Returns NULL if an error occurs.
- ///
- /// @discussion The function is same as UIGraphicsBeginImageContextWithOptions(),
- /// but it doesn't push the context to UIGraphic, so you can retain the context for reuse.
- CGContextRef _Nullable YYCGContextCreateARGBBitmapContext(CGSize size, BOOL opaque, CGFloat scale);
- /// Create a `DeviceGray` Bitmap context. Returns NULL if an error occurs.
- CGContextRef _Nullable YYCGContextCreateGrayBitmapContext(CGSize size, CGFloat scale);
- /// Get main screen's scale.
- CGFloat YYScreenScale();
- /// Get main screen's size. Height is always larger than width.
- CGSize YYScreenSize();
- /// Convert degrees to radians.
- static inline CGFloat DegreesToRadians(CGFloat degrees) {
- return degrees * M_PI / 180;
- }
- /// Convert radians to degrees.
- static inline CGFloat RadiansToDegrees(CGFloat radians) {
- return radians * 180 / M_PI;
- }
- /// Get the transform rotation.
- /// @return the rotation in radians [-PI,PI] ([-180°,180°])
- static inline CGFloat CGAffineTransformGetRotation(CGAffineTransform transform) {
- return atan2(transform.b, transform.a);
- }
- /// Get the transform's scale.x
- static inline CGFloat CGAffineTransformGetScaleX(CGAffineTransform transform) {
- return sqrt(transform.a * transform.a + transform.c * transform.c);
- }
- /// Get the transform's scale.y
- static inline CGFloat CGAffineTransformGetScaleY(CGAffineTransform transform) {
- return sqrt(transform.b * transform.b + transform.d * transform.d);
- }
- /// Get the transform's translate.x
- static inline CGFloat CGAffineTransformGetTranslateX(CGAffineTransform transform) {
- return transform.tx;
- }
- /// Get the transform's translate.y
- static inline CGFloat CGAffineTransformGetTranslateY(CGAffineTransform transform) {
- return transform.ty;
- }
- /**
- If you have 3 pair of points transformed by a same CGAffineTransform:
- p1 (transform->) q1
- p2 (transform->) q2
- p3 (transform->) q3
- This method returns the original transform matrix from these 3 pair of points.
-
- @see http://stackoverflow.com/questions/13291796/calculate-values-for-a-cgaffinetransform-from-three-points-in-each-of-two-uiview
- */
- CGAffineTransform YYCGAffineTransformGetFromPoints(CGPoint before[_Nonnull 3], CGPoint after[_Nonnull 3]);
- /// Get the transform which can converts a point from the coordinate system of a given view to another.
- CGAffineTransform YYCGAffineTransformGetFromViews(UIView *from, UIView *to);
- /// Create a skew transform.
- static inline CGAffineTransform CGAffineTransformMakeSkew(CGFloat x, CGFloat y){
- CGAffineTransform transform = CGAffineTransformIdentity;
- transform.c = -x;
- transform.b = y;
- return transform;
- }
- /// Negates/inverts a UIEdgeInsets.
- static inline UIEdgeInsets UIEdgeInsetsInvert(UIEdgeInsets insets) {
- return UIEdgeInsetsMake(-insets.top, -insets.left, -insets.bottom, -insets.right);
- }
- /// Convert CALayer's gravity string to UIViewContentMode.
- UIViewContentMode YYCAGravityToUIViewContentMode(NSString *gravity);
- /// Convert UIViewContentMode to CALayer's gravity string.
- NSString *YYUIViewContentModeToCAGravity(UIViewContentMode contentMode);
- /**
- Returns a rectangle to fit the `rect` with specified content mode.
-
- @param rect The constrant rect
- @param size The content size
- @param mode The content mode
- @return A rectangle for the given content mode.
- @discussion UIViewContentModeRedraw is same as UIViewContentModeScaleToFill.
- */
- CGRect YYCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode);
- /// Returns the center for the rectangle.
- static inline CGPoint CGRectGetCenter(CGRect rect) {
- return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
- }
- /// Returns the area of the rectangle.
- static inline CGFloat CGRectGetArea(CGRect rect) {
- if (CGRectIsNull(rect)) return 0;
- rect = CGRectStandardize(rect);
- return rect.size.width * rect.size.height;
- }
- /// Returns the distance between two points.
- static inline CGFloat CGPointGetDistanceToPoint(CGPoint p1, CGPoint p2) {
- return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
- }
- /// Returns the minmium distance between a point to a rectangle.
- static inline CGFloat CGPointGetDistanceToRect(CGPoint p, CGRect r) {
- r = CGRectStandardize(r);
- if (CGRectContainsPoint(r, p)) return 0;
- CGFloat distV, distH;
- if (CGRectGetMinY(r) <= p.y && p.y <= CGRectGetMaxY(r)) {
- distV = 0;
- } else {
- distV = p.y < CGRectGetMinY(r) ? CGRectGetMinY(r) - p.y : p.y - CGRectGetMaxY(r);
- }
- if (CGRectGetMinX(r) <= p.x && p.x <= CGRectGetMaxX(r)) {
- distH = 0;
- } else {
- distH = p.x < CGRectGetMinX(r) ? CGRectGetMinX(r) - p.x : p.x - CGRectGetMaxX(r);
- }
- return MAX(distV, distH);
- }
- /// Convert point to pixel.
- static inline CGFloat CGFloatToPixel(CGFloat value) {
- return value * YYScreenScale();
- }
- /// Convert pixel to point.
- static inline CGFloat CGFloatFromPixel(CGFloat value) {
- return value / YYScreenScale();
- }
- /// floor point value for pixel-aligned
- static inline CGFloat CGFloatPixelFloor(CGFloat value) {
- CGFloat scale = YYScreenScale();
- return floor(value * scale) / scale;
- }
- /// round point value for pixel-aligned
- static inline CGFloat CGFloatPixelRound(CGFloat value) {
- CGFloat scale = YYScreenScale();
- return round(value * scale) / scale;
- }
- /// ceil point value for pixel-aligned
- static inline CGFloat CGFloatPixelCeil(CGFloat value) {
- CGFloat scale = YYScreenScale();
- return ceil(value * scale) / scale;
- }
- /// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned)
- static inline CGFloat CGFloatPixelHalf(CGFloat value) {
- CGFloat scale = YYScreenScale();
- return (floor(value * scale) + 0.5) / scale;
- }
- /// floor point value for pixel-aligned
- static inline CGPoint CGPointPixelFloor(CGPoint point) {
- CGFloat scale = YYScreenScale();
- return CGPointMake(floor(point.x * scale) / scale,
- floor(point.y * scale) / scale);
- }
- /// round point value for pixel-aligned
- static inline CGPoint CGPointPixelRound(CGPoint point) {
- CGFloat scale = YYScreenScale();
- return CGPointMake(round(point.x * scale) / scale,
- round(point.y * scale) / scale);
- }
- /// ceil point value for pixel-aligned
- static inline CGPoint CGPointPixelCeil(CGPoint point) {
- CGFloat scale = YYScreenScale();
- return CGPointMake(ceil(point.x * scale) / scale,
- ceil(point.y * scale) / scale);
- }
- /// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned)
- static inline CGPoint CGPointPixelHalf(CGPoint point) {
- CGFloat scale = YYScreenScale();
- return CGPointMake((floor(point.x * scale) + 0.5) / scale,
- (floor(point.y * scale) + 0.5) / scale);
- }
- /// floor point value for pixel-aligned
- static inline CGSize CGSizePixelFloor(CGSize size) {
- CGFloat scale = YYScreenScale();
- return CGSizeMake(floor(size.width * scale) / scale,
- floor(size.height * scale) / scale);
- }
- /// round point value for pixel-aligned
- static inline CGSize CGSizePixelRound(CGSize size) {
- CGFloat scale = YYScreenScale();
- return CGSizeMake(round(size.width * scale) / scale,
- round(size.height * scale) / scale);
- }
- /// ceil point value for pixel-aligned
- static inline CGSize CGSizePixelCeil(CGSize size) {
- CGFloat scale = YYScreenScale();
- return CGSizeMake(ceil(size.width * scale) / scale,
- ceil(size.height * scale) / scale);
- }
- /// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned)
- static inline CGSize CGSizePixelHalf(CGSize size) {
- CGFloat scale = YYScreenScale();
- return CGSizeMake((floor(size.width * scale) + 0.5) / scale,
- (floor(size.height * scale) + 0.5) / scale);
- }
- /// floor point value for pixel-aligned
- static inline CGRect CGRectPixelFloor(CGRect rect) {
- CGPoint origin = CGPointPixelCeil(rect.origin);
- CGPoint corner = CGPointPixelFloor(CGPointMake(rect.origin.x + rect.size.width,
- rect.origin.y + rect.size.height));
- CGRect ret = CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y);
- if (ret.size.width < 0) ret.size.width = 0;
- if (ret.size.height < 0) ret.size.height = 0;
- return ret;
- }
- /// round point value for pixel-aligned
- static inline CGRect CGRectPixelRound(CGRect rect) {
- CGPoint origin = CGPointPixelRound(rect.origin);
- CGPoint corner = CGPointPixelRound(CGPointMake(rect.origin.x + rect.size.width,
- rect.origin.y + rect.size.height));
- return CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y);
- }
- /// ceil point value for pixel-aligned
- static inline CGRect CGRectPixelCeil(CGRect rect) {
- CGPoint origin = CGPointPixelFloor(rect.origin);
- CGPoint corner = CGPointPixelCeil(CGPointMake(rect.origin.x + rect.size.width,
- rect.origin.y + rect.size.height));
- return CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y);
- }
- /// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned)
- static inline CGRect CGRectPixelHalf(CGRect rect) {
- CGPoint origin = CGPointPixelHalf(rect.origin);
- CGPoint corner = CGPointPixelHalf(CGPointMake(rect.origin.x + rect.size.width,
- rect.origin.y + rect.size.height));
- return CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y);
- }
- /// floor UIEdgeInset for pixel-aligned
- static inline UIEdgeInsets UIEdgeInsetPixelFloor(UIEdgeInsets insets) {
- insets.top = CGFloatPixelFloor(insets.top);
- insets.left = CGFloatPixelFloor(insets.left);
- insets.bottom = CGFloatPixelFloor(insets.bottom);
- insets.right = CGFloatPixelFloor(insets.right);
- return insets;
- }
- /// ceil UIEdgeInset for pixel-aligned
- static inline UIEdgeInsets UIEdgeInsetPixelCeil(UIEdgeInsets insets) {
- insets.top = CGFloatPixelCeil(insets.top);
- insets.left = CGFloatPixelCeil(insets.left);
- insets.bottom = CGFloatPixelCeil(insets.bottom);
- insets.right = CGFloatPixelCeil(insets.right);
- return insets;
- }
- // main screen's scale
- #ifndef kScreenScale
- #define kScreenScale YYScreenScale()
- #endif
- // main screen's size (portrait)
- #ifndef kScreenSize
- #define kScreenSize YYScreenSize()
- #endif
- // main screen's width (portrait)
- #ifndef kWidth
- #define kWidth YYScreenSize().width
- #endif
- // main screen's height (portrait)
- #ifndef kHeight
- #define kHeight YYScreenSize().height
- #endif
- NS_ASSUME_NONNULL_END
- YY_EXTERN_C_END
|