From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001 From: 单军华 Date: Wed, 11 Jul 2018 10:47:42 +0800 Subject: [PATCH] 首次上传 --- screendisplay/Pods/YYText/YYText/Utility/YYTextUtilities.h | 563 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 563 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/YYText/YYText/Utility/YYTextUtilities.h b/screendisplay/Pods/YYText/YYText/Utility/YYTextUtilities.h new file mode 100755 index 0000000..9410c9b --- /dev/null +++ b/screendisplay/Pods/YYText/YYText/Utility/YYTextUtilities.h @@ -0,0 +1,563 @@ +// +// YYTextUtilities.h +// YYText <https://github.com/ibireme/YYText> +// +// Created by ibireme on 15/4/6. +// 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> +#import <CoreText/CoreText.h> + + +#ifndef YYTEXT_CLAMP // return the clamped value +#define YYTEXT_CLAMP(_x_, _low_, _high_) (((_x_) > (_high_)) ? (_high_) : (((_x_) < (_low_)) ? (_low_) : (_x_))) +#endif + +#ifndef YYTEXT_SWAP // swap two value +#define YYTEXT_SWAP(_a_, _b_) do { __typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = _tmp_; } while (0) +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + Whether the character is 'line break char': + U+000D (\\r or CR) + U+2028 (Unicode line separator) + U+000A (\\n or LF) + U+2029 (Unicode paragraph separator) + + @param c A character + @return YES or NO. + */ +static inline BOOL YYTextIsLinebreakChar(unichar c) { + switch (c) { + case 0x000D: + case 0x2028: + case 0x000A: + case 0x2029: + return YES; + default: + return NO; + } +} + +/** + Whether the string is a 'line break': + U+000D (\\r or CR) + U+2028 (Unicode line separator) + U+000A (\\n or LF) + U+2029 (Unicode paragraph separator) + \\r\\n, in that order (also known as CRLF) + + @param str A string + @return YES or NO. + */ +static inline BOOL YYTextIsLinebreakString(NSString * _Nullable str) { + if (str.length > 2 || str.length == 0) return NO; + if (str.length == 1) { + unichar c = [str characterAtIndex:0]; + return YYTextIsLinebreakChar(c); + } else { + return ([str characterAtIndex:0] == '\r') && ([str characterAtIndex:1] == '\n'); + } +} + +/** + If the string has a 'line break' suffix, return the 'line break' length. + + @param str A string. + @return The length of the tail line break: 0, 1 or 2. + */ +static inline NSUInteger YYTextLinebreakTailLength(NSString * _Nullable str) { + if (str.length >= 2) { + unichar c2 = [str characterAtIndex:str.length - 1]; + if (YYTextIsLinebreakChar(c2)) { + unichar c1 = [str characterAtIndex:str.length - 2]; + if (c1 == '\r' && c2 == '\n') return 2; + else return 1; + } else { + return 0; + } + } else if (str.length == 1) { + return YYTextIsLinebreakChar([str characterAtIndex:0]) ? 1 : 0; + } else { + return 0; + } +} + +/** + Convert `UIDataDetectorTypes` to `NSTextCheckingType`. + + @param types The `UIDataDetectorTypes` type. + @return The `NSTextCheckingType` type. + */ +static inline NSTextCheckingType YYTextNSTextCheckingTypeFromUIDataDetectorType(UIDataDetectorTypes types) { + NSTextCheckingType t = 0; + if (types & UIDataDetectorTypePhoneNumber) t |= NSTextCheckingTypePhoneNumber; + if (types & UIDataDetectorTypeLink) t |= NSTextCheckingTypeLink; + if (types & UIDataDetectorTypeAddress) t |= NSTextCheckingTypeAddress; + if (types & UIDataDetectorTypeCalendarEvent) t |= NSTextCheckingTypeDate; + return t; +} + +/** + Whether the font is `AppleColorEmoji` font. + + @param font A font. + @return YES: the font is Emoji, NO: the font is not Emoji. + */ +static inline BOOL YYTextUIFontIsEmoji(UIFont *font) { + return [font.fontName isEqualToString:@"AppleColorEmoji"]; +} + +/** + Whether the font is `AppleColorEmoji` font. + + @param font A font. + @return YES: the font is Emoji, NO: the font is not Emoji. + */ +static inline BOOL YYTextCTFontIsEmoji(CTFontRef font) { + BOOL isEmoji = NO; + CFStringRef name = CTFontCopyPostScriptName(font); + if (name && CFEqual(CFSTR("AppleColorEmoji"), name)) isEmoji = YES; + if (name) CFRelease(name); + return isEmoji; +} + +/** + Whether the font is `AppleColorEmoji` font. + + @param font A font. + @return YES: the font is Emoji, NO: the font is not Emoji. + */ +static inline BOOL YYTextCGFontIsEmoji(CGFontRef font) { + BOOL isEmoji = NO; + CFStringRef name = CGFontCopyPostScriptName(font); + if (name && CFEqual(CFSTR("AppleColorEmoji"), name)) isEmoji = YES; + if (name) CFRelease(name); + return isEmoji; +} + +/** + Whether the font contains color bitmap glyphs. + + @discussion Only `AppleColorEmoji` contains color bitmap glyphs in iOS system fonts. + @param font A font. + @return YES: the font contains color bitmap glyphs, NO: the font has no color bitmap glyph. + */ +static inline BOOL YYTextCTFontContainsColorBitmapGlyphs(CTFontRef font) { + return (CTFontGetSymbolicTraits(font) & kCTFontTraitColorGlyphs) != 0; +} + +/** + Whether the glyph is bitmap. + + @param font The glyph's font. + @param glyph The glyph which is created from the specified font. + @return YES: the glyph is bitmap, NO: the glyph is vector. + */ +static inline BOOL YYTextCGGlyphIsBitmap(CTFontRef font, CGGlyph glyph) { + if (!font && !glyph) return NO; + if (!YYTextCTFontContainsColorBitmapGlyphs(font)) return NO; + CGPathRef path = CTFontCreatePathForGlyph(font, glyph, NULL); + if (path) { + CFRelease(path); + return NO; + } + return YES; +} + +/** + Get the `AppleColorEmoji` font's ascent with a specified font size. + It may used to create custom emoji. + + @param fontSize The specified font size. + @return The font ascent. + */ +static inline CGFloat YYTextEmojiGetAscentWithFontSize(CGFloat fontSize) { + if (fontSize < 16) { + return 1.25 * fontSize; + } else if (16 <= fontSize && fontSize <= 24) { + return 0.5 * fontSize + 12; + } else { + return fontSize; + } +} + +/** + Get the `AppleColorEmoji` font's descent with a specified font size. + It may used to create custom emoji. + + @param fontSize The specified font size. + @return The font descent. + */ +static inline CGFloat YYTextEmojiGetDescentWithFontSize(CGFloat fontSize) { + if (fontSize < 16) { + return 0.390625 * fontSize; + } else if (16 <= fontSize && fontSize <= 24) { + return 0.15625 * fontSize + 3.75; + } else { + return 0.3125 * fontSize; + } + return 0; +} + +/** + Get the `AppleColorEmoji` font's glyph bounding rect with a specified font size. + It may used to create custom emoji. + + @param fontSize The specified font size. + @return The font glyph bounding rect. + */ +static inline CGRect YYTextEmojiGetGlyphBoundingRectWithFontSize(CGFloat fontSize) { + CGRect rect; + rect.origin.x = 0.75; + rect.size.width = rect.size.height = YYTextEmojiGetAscentWithFontSize(fontSize); + if (fontSize < 16) { + rect.origin.y = -0.2525 * fontSize; + } else if (16 <= fontSize && fontSize <= 24) { + rect.origin.y = 0.1225 * fontSize -6; + } else { + rect.origin.y = -0.1275 * fontSize; + } + return rect; +} + + +/** + Get the character set which should rotate in vertical form. + @return The shared character set. + */ +NSCharacterSet *YYTextVerticalFormRotateCharacterSet(); + +/** + Get the character set which should rotate and move in vertical form. + @return The shared character set. + */ +NSCharacterSet *YYTextVerticalFormRotateAndMoveCharacterSet(); + + + +/// Convert degrees to radians. +static inline CGFloat YYTextDegreesToRadians(CGFloat degrees) { + return degrees * M_PI / 180; +} + +/// Convert radians to degrees. +static inline CGFloat YYTextRadiansToDegrees(CGFloat radians) { + return radians * 180 / M_PI; +} + + + +/// Get the transform rotation. +/// @return the rotation in radians [-PI,PI] ([-180��,180��]) +static inline CGFloat YYTextCGAffineTransformGetRotation(CGAffineTransform transform) { + return atan2(transform.b, transform.a); +} + +/// Get the transform's scale.x +static inline CGFloat YYTextCGAffineTransformGetScaleX(CGAffineTransform transform) { + return sqrt(transform.a * transform.a + transform.c * transform.c); +} + +/// Get the transform's scale.y +static inline CGFloat YYTextCGAffineTransformGetScaleY(CGAffineTransform transform) { + return sqrt(transform.b * transform.b + transform.d * transform.d); +} + +/// Get the transform's translate.x +static inline CGFloat YYTextCGAffineTransformGetTranslateX(CGAffineTransform transform) { + return transform.tx; +} + +/// Get the transform's translate.y +static inline CGFloat YYTextCGAffineTransformGetTranslateY(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 YYTextCGAffineTransformGetFromPoints(CGPoint before[3], CGPoint after[3]); + +/// Get the transform which can converts a point from the coordinate system of a given view to another. +CGAffineTransform YYTextCGAffineTransformGetFromViews(UIView *from, UIView *to); + +/// Create a skew transform. +static inline CGAffineTransform YYTextCGAffineTransformMakeSkew(CGFloat x, CGFloat y){ + CGAffineTransform transform = CGAffineTransformIdentity; + transform.c = -x; + transform.b = y; + return transform; +} + +/// Negates/inverts a UIEdgeInsets. +static inline UIEdgeInsets YYTextUIEdgeInsetsInvert(UIEdgeInsets insets) { + return UIEdgeInsetsMake(-insets.top, -insets.left, -insets.bottom, -insets.right); +} + +/// Convert CALayer's gravity string to UIViewContentMode. +UIViewContentMode YYTextCAGravityToUIViewContentMode(NSString *gravity); + +/// Convert UIViewContentMode to CALayer's gravity string. +NSString *YYTextUIViewContentModeToCAGravity(UIViewContentMode contentMode); + + + +/** + Returns a rectangle to fit the @param 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 YYTextCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode); + +/// Returns the center for the rectangle. +static inline CGPoint YYTextCGRectGetCenter(CGRect rect) { + return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); +} + +/// Returns the area of the rectangle. +static inline CGFloat YYTextCGRectGetArea(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 YYTextCGPointGetDistanceToPoint(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 YYTextCGPointGetDistanceToRect(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); +} + + +/// Get main screen's scale. +CGFloat YYTextScreenScale(); + +/// Get main screen's size. Height is always larger than width. +CGSize YYTextScreenSize(); + +/// Convert point to pixel. +static inline CGFloat YYTextCGFloatToPixel(CGFloat value) { + return value * YYTextScreenScale(); +} + +/// Convert pixel to point. +static inline CGFloat YYTextCGFloatFromPixel(CGFloat value) { + return value / YYTextScreenScale(); +} + +/// floor point value for pixel-aligned +static inline CGFloat YYTextCGFloatPixelFloor(CGFloat value) { + CGFloat scale = YYTextScreenScale(); + return floor(value * scale) / scale; +} + +/// round point value for pixel-aligned +static inline CGFloat YYTextCGFloatPixelRound(CGFloat value) { + CGFloat scale = YYTextScreenScale(); + return round(value * scale) / scale; +} + +/// ceil point value for pixel-aligned +static inline CGFloat YYTextCGFloatPixelCeil(CGFloat value) { + CGFloat scale = YYTextScreenScale(); + return ceil(value * scale) / scale; +} + +/// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned) +static inline CGFloat YYTextCGFloatPixelHalf(CGFloat value) { + CGFloat scale = YYTextScreenScale(); + return (floor(value * scale) + 0.5) / scale; +} + +/// floor point value for pixel-aligned +static inline CGPoint YYTextCGPointPixelFloor(CGPoint point) { + CGFloat scale = YYTextScreenScale(); + return CGPointMake(floor(point.x * scale) / scale, + floor(point.y * scale) / scale); +} + +/// round point value for pixel-aligned +static inline CGPoint YYTextCGPointPixelRound(CGPoint point) { + CGFloat scale = YYTextScreenScale(); + return CGPointMake(round(point.x * scale) / scale, + round(point.y * scale) / scale); +} + +/// ceil point value for pixel-aligned +static inline CGPoint YYTextCGPointPixelCeil(CGPoint point) { + CGFloat scale = YYTextScreenScale(); + 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 YYTextCGPointPixelHalf(CGPoint point) { + CGFloat scale = YYTextScreenScale(); + 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 YYTextCGSizePixelFloor(CGSize size) { + CGFloat scale = YYTextScreenScale(); + return CGSizeMake(floor(size.width * scale) / scale, + floor(size.height * scale) / scale); +} + +/// round point value for pixel-aligned +static inline CGSize YYTextCGSizePixelRound(CGSize size) { + CGFloat scale = YYTextScreenScale(); + return CGSizeMake(round(size.width * scale) / scale, + round(size.height * scale) / scale); +} + +/// ceil point value for pixel-aligned +static inline CGSize YYTextCGSizePixelCeil(CGSize size) { + CGFloat scale = YYTextScreenScale(); + 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 YYTextCGSizePixelHalf(CGSize size) { + CGFloat scale = YYTextScreenScale(); + 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 YYTextCGRectPixelFloor(CGRect rect) { + CGPoint origin = YYTextCGPointPixelCeil(rect.origin); + CGPoint corner = YYTextCGPointPixelFloor(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 YYTextCGRectPixelRound(CGRect rect) { + CGPoint origin = YYTextCGPointPixelRound(rect.origin); + CGPoint corner = YYTextCGPointPixelRound(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 YYTextCGRectPixelCeil(CGRect rect) { + CGPoint origin = YYTextCGPointPixelFloor(rect.origin); + CGPoint corner = YYTextCGPointPixelCeil(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 YYTextCGRectPixelHalf(CGRect rect) { + CGPoint origin = YYTextCGPointPixelHalf(rect.origin); + CGPoint corner = YYTextCGPointPixelHalf(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 YYTextUIEdgeInsetPixelFloor(UIEdgeInsets insets) { + insets.top = YYTextCGFloatPixelFloor(insets.top); + insets.left = YYTextCGFloatPixelFloor(insets.left); + insets.bottom = YYTextCGFloatPixelFloor(insets.bottom); + insets.right = YYTextCGFloatPixelFloor(insets.right); + return insets; +} + +/// ceil UIEdgeInset for pixel-aligned +static inline UIEdgeInsets YYTextUIEdgeInsetPixelCeil(UIEdgeInsets insets) { + insets.top = YYTextCGFloatPixelCeil(insets.top); + insets.left = YYTextCGFloatPixelCeil(insets.left); + insets.bottom = YYTextCGFloatPixelCeil(insets.bottom); + insets.right = YYTextCGFloatPixelCeil(insets.right); + return insets; +} + + + +static inline UIFont * _Nullable YYTextFontWithBold(UIFont *font) { + if (![font respondsToSelector:@selector(fontDescriptor)]) return font; + return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold] size:font.pointSize]; +} + +static inline UIFont * _Nullable YYTextFontWithItalic(UIFont *font) { + if (![font respondsToSelector:@selector(fontDescriptor)]) return font; + return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic] size:font.pointSize]; +} + +static inline UIFont * _Nullable YYTextFontWithBoldItalic(UIFont *font) { + if (![font respondsToSelector:@selector(fontDescriptor)]) return font; + return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold | UIFontDescriptorTraitItalic] size:font.pointSize]; +} + + + +/** + Convert CFRange to NSRange + @param range CFRange @return NSRange + */ +static inline NSRange YYTextNSRangeFromCFRange(CFRange range) { + return NSMakeRange(range.location, range.length); +} + +/** + Convert NSRange to CFRange + @param range NSRange @return CFRange + */ +static inline CFRange YYTextCFRangeFromNSRange(NSRange range) { + return CFRangeMake(range.location, range.length); +} + + +/// Returns YES in App Extension. +BOOL YYTextIsAppExtension(); + +/// Returns nil in App Extension. +UIApplication * _Nullable YYTextSharedApplication(); + +NS_ASSUME_NONNULL_END -- Gitblit v1.8.0