From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001 From: 单军华 Date: Wed, 11 Jul 2018 10:47:42 +0800 Subject: [PATCH] 首次上传 --- screendisplay/Pods/YYAsyncLayer/YYAsyncLayer/YYAsyncLayer.m | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 187 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/YYAsyncLayer/YYAsyncLayer/YYAsyncLayer.m b/screendisplay/Pods/YYAsyncLayer/YYAsyncLayer/YYAsyncLayer.m new file mode 100755 index 0000000..c477718 --- /dev/null +++ b/screendisplay/Pods/YYAsyncLayer/YYAsyncLayer/YYAsyncLayer.m @@ -0,0 +1,187 @@ +// +// YYAsyncLayer.m +// YYKit <https://github.com/ibireme/YYKit> +// +// Created by ibireme on 15/4/11. +// 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 "YYAsyncLayer.h" +#import "YYSentinel.h" + +#if __has_include("YYDispatchQueuePool.h") +#import "YYDispatchQueuePool.h" +#else +#import <libkern/OSAtomic.h> +#endif + +/// Global display queue, used for content rendering. +static dispatch_queue_t YYAsyncLayerGetDisplayQueue() { +#ifdef YYDispatchQueuePool_h + return YYDispatchQueueGetForQOS(NSQualityOfServiceUserInitiated); +#else +#define MAX_QUEUE_COUNT 16 + static int queueCount; + static dispatch_queue_t queues[MAX_QUEUE_COUNT]; + static dispatch_once_t onceToken; + static int32_t counter = 0; + dispatch_once(&onceToken, ^{ + queueCount = (int)[NSProcessInfo processInfo].activeProcessorCount; + queueCount = queueCount < 1 ? 1 : queueCount > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : queueCount; + if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { + for (NSUInteger i = 0; i < queueCount; i++) { + dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0); + queues[i] = dispatch_queue_create("com.ibireme.yykit.render", attr); + } + } else { + for (NSUInteger i = 0; i < queueCount; i++) { + queues[i] = dispatch_queue_create("com.ibireme.yykit.render", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(queues[i], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + } + } + }); + int32_t cur = OSAtomicIncrement32(&counter); + if (cur < 0) cur = -cur; + return queues[(cur) % queueCount]; +#undef MAX_QUEUE_COUNT +#endif +} + +static dispatch_queue_t YYAsyncLayerGetReleaseQueue() { +#ifdef YYDispatchQueuePool_h + return YYDispatchQueueGetForQOS(NSQualityOfServiceDefault); +#else + return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); +#endif +} + + +@implementation YYAsyncLayerDisplayTask +@end + + +@implementation YYAsyncLayer { + YYSentinel *_sentinel; +} + +#pragma mark - Override + ++ (id)defaultValueForKey:(NSString *)key { + if ([key isEqualToString:@"displaysAsynchronously"]) { + return @(YES); + } else { + return [super defaultValueForKey:key]; + } +} + +- (instancetype)init { + self = [super init]; + static CGFloat scale; //global + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + scale = [UIScreen mainScreen].scale; + }); + self.contentsScale = scale; + _sentinel = [YYSentinel new]; + _displaysAsynchronously = YES; + return self; +} + +- (void)dealloc { + [_sentinel increase]; +} + +- (void)setNeedsDisplay { + [self _cancelAsyncDisplay]; + [super setNeedsDisplay]; +} + +- (void)display { + super.contents = super.contents; + [self _displayAsync:_displaysAsynchronously]; +} + +#pragma mark - Private + +- (void)_displayAsync:(BOOL)async { + __strong id<YYAsyncLayerDelegate> delegate = self.delegate; + YYAsyncLayerDisplayTask *task = [delegate newAsyncDisplayTask]; + if (!task.display) { + if (task.willDisplay) task.willDisplay(self); + self.contents = nil; + if (task.didDisplay) task.didDisplay(self, YES); + return; + } + + if (async) { + if (task.willDisplay) task.willDisplay(self); + YYSentinel *sentinel = _sentinel; + int32_t value = sentinel.value; + BOOL (^isCancelled)() = ^BOOL() { + return value != sentinel.value; + }; + CGSize size = self.bounds.size; + BOOL opaque = self.opaque; + CGFloat scale = self.contentsScale; + if (size.width < 1 || size.height < 1) { + CGImageRef image = (__bridge_retained CGImageRef)(self.contents); + self.contents = nil; + if (image) { + dispatch_async(YYAsyncLayerGetReleaseQueue(), ^{ + CFRelease(image); + }); + } + if (task.didDisplay) task.didDisplay(self, YES); + return; + } + + dispatch_async(YYAsyncLayerGetDisplayQueue(), ^{ + if (isCancelled()) return; + UIGraphicsBeginImageContextWithOptions(size, opaque, scale); + CGContextRef context = UIGraphicsGetCurrentContext(); + task.display(context, size, isCancelled); + if (isCancelled()) { + UIGraphicsEndImageContext(); + dispatch_async(dispatch_get_main_queue(), ^{ + if (task.didDisplay) task.didDisplay(self, NO); + }); + return; + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + if (isCancelled()) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (task.didDisplay) task.didDisplay(self, NO); + }); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + if (isCancelled()) { + if (task.didDisplay) task.didDisplay(self, NO); + } else { + self.contents = (__bridge id)(image.CGImage); + if (task.didDisplay) task.didDisplay(self, YES); + } + }); + }); + } else { + [_sentinel increase]; + if (task.willDisplay) task.willDisplay(self); + UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale); + CGContextRef context = UIGraphicsGetCurrentContext(); + task.display(context, self.bounds.size, ^{return NO;}); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + self.contents = (__bridge id)(image.CGImage); + if (task.didDisplay) task.didDisplay(self, YES); + } +} + +- (void)_cancelAsyncDisplay { + [_sentinel increase]; +} + +@end -- Gitblit v1.8.0