You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by so...@apache.org on 2017/02/28 02:30:05 UTC

[25/50] incubator-weex git commit: + [ios] feature : add box-shadow for iOS

+ [ios] feature : add box-shadow for iOS


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/64013ea4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/64013ea4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/64013ea4

Branch: refs/heads/0.11-dev
Commit: 64013ea4b9cf61b1cd017c18473dc80007fe66d9
Parents: 7ed89f9
Author: \u9f50\u5c71 <su...@163.com>
Authored: Wed Feb 22 23:05:14 2017 +0800
Committer: \u9f50\u5c71 <su...@163.com>
Committed: Wed Feb 22 23:05:14 2017 +0800

----------------------------------------------------------------------
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj      | 16 ++++
 ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.h | 19 +++++
 ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.m | 92 +++++++++++++++++++++
 ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h  |  7 +-
 ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m  | 89 +++++++++++++++-----
 5 files changed, 199 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/64013ea4/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 6330741..86687e6 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -223,6 +223,10 @@
 		C4B834281DE69B09007AD27E /* WXPickerModule.h in Headers */ = {isa = PBXBuildFile; fileRef = C4B834261DE69B09007AD27E /* WXPickerModule.h */; };
 		C4C30DE81E1B833D00786B6C /* WXComponent+PseudoClassManagement.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C30DE61E1B833D00786B6C /* WXComponent+PseudoClassManagement.m */; };
 		C4C30DE91E1B833D00786B6C /* WXComponent+PseudoClassManagement.h in Headers */ = {isa = PBXBuildFile; fileRef = C4C30DE71E1B833D00786B6C /* WXComponent+PseudoClassManagement.h */; };
+		C4D872211E5DDEDA00E39BC1 /* WXInnerLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C4D8721F1E5DDEDA00E39BC1 /* WXInnerLayer.m */; };
+		C4D872221E5DDEDA00E39BC1 /* WXInnerLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = C4D872201E5DDEDA00E39BC1 /* WXInnerLayer.h */; };
+		C4D872251E5DDF7500E39BC1 /* WXBoxShadow.h in Headers */ = {isa = PBXBuildFile; fileRef = C4D872231E5DDF7500E39BC1 /* WXBoxShadow.h */; };
+		C4D872261E5DDF7500E39BC1 /* WXBoxShadow.m in Sources */ = {isa = PBXBuildFile; fileRef = C4D872241E5DDF7500E39BC1 /* WXBoxShadow.m */; };
 		C4F012791E1502A6003378D0 /* SRWebSocket+Weex.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F012721E1502A6003378D0 /* SRWebSocket+Weex.h */; };
 		C4F0127A1E1502A6003378D0 /* SRWebSocket+Weex.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F012731E1502A6003378D0 /* SRWebSocket+Weex.m */; };
 		C4F0127B1E1502A6003378D0 /* WXWebSocketDefaultImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F012741E1502A6003378D0 /* WXWebSocketDefaultImpl.h */; };
@@ -512,6 +516,10 @@
 		C4B834261DE69B09007AD27E /* WXPickerModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXPickerModule.h; sourceTree = "<group>"; };
 		C4C30DE61E1B833D00786B6C /* WXComponent+PseudoClassManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WXComponent+PseudoClassManagement.m"; sourceTree = "<group>"; };
 		C4C30DE71E1B833D00786B6C /* WXComponent+PseudoClassManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WXComponent+PseudoClassManagement.h"; sourceTree = "<group>"; };
+		C4D8721F1E5DDEDA00E39BC1 /* WXInnerLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInnerLayer.m; sourceTree = "<group>"; };
+		C4D872201E5DDEDA00E39BC1 /* WXInnerLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXInnerLayer.h; sourceTree = "<group>"; };
+		C4D872231E5DDF7500E39BC1 /* WXBoxShadow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXBoxShadow.h; sourceTree = "<group>"; };
+		C4D872241E5DDF7500E39BC1 /* WXBoxShadow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXBoxShadow.m; sourceTree = "<group>"; };
 		C4F012721E1502A6003378D0 /* SRWebSocket+Weex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SRWebSocket+Weex.h"; sourceTree = "<group>"; };
 		C4F012731E1502A6003378D0 /* SRWebSocket+Weex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SRWebSocket+Weex.m"; sourceTree = "<group>"; };
 		C4F012741E1502A6003378D0 /* WXWebSocketDefaultImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXWebSocketDefaultImpl.h; sourceTree = "<group>"; };
@@ -679,6 +687,8 @@
 		7461F88B1CFB373100F62D44 /* Display */ = {
 			isa = PBXGroup;
 			children = (
+				C4D8721F1E5DDEDA00E39BC1 /* WXInnerLayer.m */,
+				C4D872201E5DDEDA00E39BC1 /* WXInnerLayer.h */,
 				7461F88C1CFB373100F62D44 /* WXDisplayQueue.h */,
 				7461F88D1CFB373100F62D44 /* WXDisplayQueue.m */,
 				7461F88E1CFB373100F62D44 /* WXLayer.h */,
@@ -938,6 +948,8 @@
 		77D161481C02E3670010B15B /* Utility */ = {
 			isa = PBXGroup;
 			children = (
+				C4D872231E5DDF7500E39BC1 /* WXBoxShadow.h */,
+				C4D872241E5DDF7500E39BC1 /* WXBoxShadow.m */,
 				59D3CA481CFC3CE1008835DC /* NSTimer+Weex.h */,
 				59D3CA491CFC3CE1008835DC /* NSTimer+Weex.m */,
 				77D161491C02E3790010B15B /* WXConvert.h */,
@@ -1146,6 +1158,8 @@
 				D362F94F1C83EDA20003F546 /* WXWebViewModule.h in Headers */,
 				C4F012861E150307003378D0 /* WXWebSocketLoader.h in Headers */,
 				77D161381C02DE940010B15B /* WXBridgeManager.h in Headers */,
+				C4D872251E5DDF7500E39BC1 /* WXBoxShadow.h in Headers */,
+				C4D872221E5DDEDA00E39BC1 /* WXInnerLayer.h in Headers */,
 				2A919DA61E321F1F006EB6B5 /* WXBridgeMethod.h in Headers */,
 				77D161281C02DE1A0010B15B /* WXSDKManager.h in Headers */,
 				59CE27E81CC387DB000BE37A /* WXEmbedComponent.h in Headers */,
@@ -1468,6 +1482,7 @@
 				74862F7E1E03A0F300B7A041 /* WXModuleMethod.m in Sources */,
 				742AD7341DF98C45007DC46C /* WXResourceResponse.m in Sources */,
 				77E65A161C155EB5008B8775 /* WXTextComponent.m in Sources */,
+				C4D872261E5DDF7500E39BC1 /* WXBoxShadow.m in Sources */,
 				746319031C60AFC100EFEBD4 /* WXThreadSafeCounter.m in Sources */,
 				74A4BAA71CB4F98300195969 /* WXStreamModule.m in Sources */,
 				59597F991D2A041700EE9317 /* WXDebugLoggerBridge.m in Sources */,
@@ -1501,6 +1516,7 @@
 				744BEA561D05178F00452B5D /* WXComponent+Display.m in Sources */,
 				7408C48F1CFB345D000BCCD0 /* WXComponent+Events.m in Sources */,
 				C4F012871E150307003378D0 /* WXWebSocketLoader.m in Sources */,
+				C4D872211E5DDEDA00E39BC1 /* WXInnerLayer.m in Sources */,
 				745ED2DB1C5F2C7E002DB5A8 /* WXView.m in Sources */,
 				DC03ADB91D508719003F76E7 /* WXTextAreaComponent.m in Sources */,
 				59A596231CB6311F0012CD52 /* WXNavigatorModule.m in Sources */,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/64013ea4/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.h b/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.h
new file mode 100644
index 0000000..f3b2bf4
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.h
@@ -0,0 +1,19 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import <QuartzCore/QuartzCore.h>
+
+@interface WXInnerLayer : CAGradientLayer
+
+@property CGFloat boxShadowRadius;
+@property CGColorRef boxShadowColor;
+@property CGSize boxShadowOffset;
+@property CGFloat boxShadowOpacity;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/64013ea4/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.m b/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.m
new file mode 100644
index 0000000..fa50867
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXInnerLayer.m
@@ -0,0 +1,92 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXInnerLayer.h"
+
+@implementation WXInnerLayer
+
+@dynamic boxShadowColor, boxShadowOffset, boxShadowRadius, boxShadowOpacity;
+
+- (id) init {
+    self = [super init];
+    return self;
+}
+
++ (BOOL)needsDisplayForKey:(NSString *)key {
+    if ([key isEqualToString:@"boxShadowRadius"]  || [key isEqualToString:@"boxShadowOffset"] || [key isEqualToString:@"boxShadowColor"] || [key isEqualToString:@"boxShadowOpacity"]) {
+        return YES;
+    }
+    return [super needsDisplayForKey:key];
+}
+
+- (id)actionForKey:(NSString *) key {
+    if ([key isEqualToString:@"boxShadowRadius"] || [key isEqualToString:@"boxShadowOffset"] ||[key isEqualToString:@"boxShadowColor"] ||  [key isEqualToString:@"boxShadowOpacity"] ) {
+        CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:key];
+        theAnimation.fromValue = [self.presentationLayer valueForKey:key];
+        return theAnimation;
+    }
+    return [super actionForKey:key];
+}
+
+- (void)drawInContext:(CGContextRef)context {
+    CGFloat radius = self.cornerRadius;
+    
+    CGRect rect = self.bounds;
+    if (self.borderWidth != 0) {
+        rect = CGRectInset(rect, self.borderWidth, self.borderWidth);
+        radius -= self.borderWidth;
+        radius = MAX(radius, 0);
+    }
+    
+    CGContextSetAllowsAntialiasing(context, YES);
+    CGContextSetShouldAntialias(context, YES);
+    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
+    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
+    
+    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
+    CGContextAddPath(context, bezierPath.CGPath);
+    CGContextClip(context);
+    CGMutablePathRef outer = CGPathCreateMutable();
+    CGPathAddRect(outer, NULL, CGRectInset(rect, -1*rect.size.width, -1*rect.size.height));
+    CGPathAddPath(outer, NULL, bezierPath.CGPath);
+    CGPathCloseSubpath(outer);
+    CGFloat *oldComponents = (CGFloat *)CGColorGetComponents(self.boxShadowColor);
+    CGFloat newComponents[4];
+    NSInteger numberOfComponents = CGColorGetNumberOfComponents(self.boxShadowColor);
+    switch (numberOfComponents)
+    {
+        case 2:
+        {
+            //grayscale
+            newComponents[0] = oldComponents[0];
+            newComponents[1] = oldComponents[0];
+            newComponents[2] = oldComponents[0];
+            newComponents[3] = oldComponents[1] * self.boxShadowOpacity;
+            break;
+        }
+        case 4:
+        {
+            //RGBA
+            newComponents[0] = oldComponents[0];
+            newComponents[1] = oldComponents[1];
+            newComponents[2] = oldComponents[2];
+            newComponents[3] = oldComponents[3] * self.boxShadowOpacity;
+            break;
+        }
+    }
+    CGColorRef shadowColorWithMultipliedAlpha = CGColorCreate(colorspace, newComponents);
+    CGColorSpaceRelease(colorspace);
+    CGContextSetFillColorWithColor(context, shadowColorWithMultipliedAlpha);
+    CGContextSetShadowWithColor(context, self.boxShadowOffset, self.boxShadowRadius, shadowColorWithMultipliedAlpha);
+    CGContextAddPath(context, outer);
+    CGContextEOFillPath(context);
+    CGPathRelease(outer);
+    CGColorRelease(shadowColorWithMultipliedAlpha);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/64013ea4/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h b/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h
index 6959207..9f8ba62 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.h
@@ -7,6 +7,7 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXInnerLayer.h"
 
 @interface WXBoxShadow : NSObject
 
@@ -14,7 +15,9 @@
 @property CGSize shadowOffset;
 @property CGFloat shadowRadius;
 @property BOOL isInset;
+@property (nonatomic, strong, nullable)WXInnerLayer *innerLayer;
+@property CGFloat shadowOpacity;
 
-+(void)configLayer:(UIView *)view boxShadow:(WXBoxShadow *)boxShadow;
-+(WXBoxShadow *)getBoxShadowFromString:(NSString *)string;
++(void)configLayer:(UIView *_Nullable)view boxShadow:(WXBoxShadow *_Nullable)boxShadow;
++(WXBoxShadow *_Nullable)getBoxShadowFromString:(NSString *_Nullable)string;
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/64013ea4/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m b/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m
index c1516d7..6362a43 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXBoxShadow.m
@@ -16,58 +16,95 @@
     if(!boxShadow){
         return;
     }
-    UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:view.bounds];
-    view.layer.masksToBounds = NO;
-    view.layer.shadowColor = boxShadow.shadowColor;
-    view.layer.shadowOffset = boxShadow.shadowOffset;
-    view.layer.shadowRadius = boxShadow.shadowRadius;
-    view.layer.shadowOpacity = 1.0f;
-    view.layer.shadowPath = shadowPath.CGPath;
+    if (boxShadow.isInset) {
+        if (boxShadow.innerLayer) {
+            [boxShadow.innerLayer removeFromSuperlayer];
+            boxShadow.innerLayer.frame = view.bounds;
+            [view.layer addSublayer:boxShadow.innerLayer];
+        }
+    } else {
+        UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:view.bounds];
+        view.layer.masksToBounds = NO;
+        view.layer.shadowColor = boxShadow.shadowColor;
+        view.layer.shadowOffset = boxShadow.shadowOffset;
+        view.layer.shadowRadius = boxShadow.shadowRadius;
+        view.layer.shadowOpacity = boxShadow.shadowOpacity;
+        view.layer.shadowPath = shadowPath.CGPath;
+    }
 }
 
-+(WXBoxShadow *)getBoxShadowFromString:(NSString *)string
++ (NSArray *)getBoxShadowElementsByBlank:(NSString *)string
 {
-    NSError *error = nil;
     string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
+    NSError *error = nil;
     NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\s{2,}" options:NSRegularExpressionCaseInsensitive error:&error];
     
     NSArray *arr = [regex matchesInString:string options:NSMatchingReportCompletion range:NSMakeRange(0, [string length])];
     
     arr = [[arr reverseObjectEnumerator] allObjects];
-    
     for (NSTextCheckingResult *str in arr) {
         string = [string stringByReplacingCharactersInRange:[str range] withString:@" "];
     }
-    NSMutableArray *array = [[string componentsSeparatedByString:@" "] mutableCopy];
+    NSArray *array = [string componentsSeparatedByString:@" "];
+    return array;
+}
+
++(WXBoxShadow *)getBoxShadowFromString:(NSString *)string
+{
+    if ([string length] == 0) {
+        return nil;
+    }
+    WXBoxShadow *boxShadow = [WXBoxShadow new];
+    boxShadow.shadowOpacity = 1.0f;
     
-    if (array && [array count] > 0) {
-        WXBoxShadow *boxShadow = [WXBoxShadow new];
-        if ([@"inset" isEqualToString: array[0]])
+    //parse color
+    if ([string rangeOfString:@"rgb"].location != NSNotFound) {
+        NSRange begin = [string rangeOfString:@"rgb"];
+        NSRange end = [string rangeOfString:@")"];
+        if (begin.location < end.location) {
+            NSRange range = NSMakeRange(begin.location, end.location-begin.location + 1);
+            NSString *str = [string substringWithRange:range];
+            NSString *colorStr = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
+            boxShadow.shadowColor = [WXConvert UIColor:colorStr].CGColor;
+            string = [string stringByReplacingOccurrencesOfString:str withString:@""];// remove color string
+        }
+    } else {
+        NSArray *boxShadowElements = [self getBoxShadowElementsByBlank:string];
+        NSString *str = [boxShadowElements lastObject];
+        boxShadow.shadowColor = [WXConvert UIColor:str].CGColor;
+        string = [string stringByReplacingOccurrencesOfString:str withString:@""];// remove color string
+    }
+
+    // parse remain BoxShadow Elements
+    NSMutableArray *remainBoxShadowElements = [[self getBoxShadowElementsByBlank:string] mutableCopy];
+    
+    if (remainBoxShadowElements && [remainBoxShadowElements count] > 0) {
+        if ([@"inset" isEqualToString: remainBoxShadowElements[0]])
         {
             boxShadow.isInset = YES;
-            [array removeObjectAtIndex:0];
+            [remainBoxShadowElements removeObjectAtIndex:0];
             
         }
         
-        for (int i = 0; i < [array count]-1; i++) {
+        for (int i = 0; i < [remainBoxShadowElements count]; i++) {
             switch (i) {
                 case 0:
                 {
                     CGSize size = boxShadow.shadowOffset;
-                    size.width = [WXConvert CGFloat:array[0]];
+                    size.width = [WXConvert CGFloat:remainBoxShadowElements[0]];
                     boxShadow.shadowOffset = size;
                 }
                     break;
                 case 1:
                 {
                     CGSize size = boxShadow.shadowOffset;
-                    size.height = [WXConvert CGFloat:array[1]];
+                    size.height = [WXConvert CGFloat:remainBoxShadowElements[1]];
                     boxShadow.shadowOffset = size;
                 }
                     break;
                 case 2:
                 {
-                    boxShadow.shadowRadius = [WXConvert CGFloat:array[2]];
+                    boxShadow.shadowRadius = [WXConvert CGFloat:remainBoxShadowElements[2]];
                 }
                     break;
                     
@@ -75,10 +112,18 @@
                     break;
             }
         }
-        boxShadow.shadowColor = [WXConvert UIColor:[array lastObject]].CGColor;
-        return boxShadow;
+        
+        if (boxShadow.isInset) {
+            if (!boxShadow.innerLayer) {
+                boxShadow.innerLayer = [[WXInnerLayer alloc] init];
+            }
+            boxShadow.innerLayer.boxShadowColor = boxShadow.shadowColor;
+            boxShadow.innerLayer.boxShadowOffset = boxShadow.shadowOffset;
+            boxShadow.innerLayer.boxShadowRadius = boxShadow.shadowRadius;
+            boxShadow.innerLayer.boxShadowOpacity = boxShadow.shadowOpacity;
+        }
     }
-    return nil;
+    return boxShadow;
 }