* [ios] support view compositing

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

Branch: refs/heads/0.12-dev
Commit: c6d980d30001fa50c25b6c91434cbbb85b24021f
Parents: dbe2f32
Author: 隐风 <cxf...@apache.org>
Authored: Wed Apr 5 19:48:08 2017 +0800
Committer: 隐风 <cxf...@apache.org>
Committed: Wed Apr 5 19:48:08 2017 +0800

----------------------------------------------------------------------
 .../Sources/Component/WXComponent_internal.h    |   8 +-
 .../Sources/Component/WXImageComponent.m        |  50 ++---
 .../WeexSDK/Sources/Component/WXTextComponent.m |  89 ++++-----
 .../Sources/Display/WXComponent+Display.m       | 191 ++++++++++++-------
 ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h |   2 +
 .../WeexSDK/Sources/Display/WXRoundedRect.mm    |   5 +
 ios/sdk/WeexSDK/Sources/Model/WXComponent.h     |  55 +++++-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |   7 +-
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m   |   6 +-
 9 files changed, 248 insertions(+), 165 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h 
b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 28f9d2e..00f0ef4 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -81,8 +81,8 @@
      *  Display
      */
     CALayer *_layer;
-    BOOL _composite;
-    BOOL _compositingChild;
+    BOOL _useCompositing;
+    BOOL _isCompositingChild;
     WXThreadSafeCounter *_displayCounter;
     
     UIColor *_borderTopColor;
@@ -185,6 +185,10 @@
 
 - (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles 
attributes:(NSMutableDictionary *)attributes;
 
+- (void)_initCompositingAttribute:(NSDictionary *)attributes;
+
+- (BOOL)_bitmapOpaqueWithSize:(CGSize)size;
+
 - (void)_updateNavBarAttributes:(NSDictionary *)attributes;
 
 - (void)_handleFirstScreenTime;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
index d5d9ca6..1e2594c 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
@@ -158,38 +158,21 @@ static dispatch_queue_t WXImageUpdateQueue;
     
 }
 
-- (WXDisplayBlock)displayBlock
+- (BOOL)needsDrawRect
 {
-    if ([self isViewLoaded]) {
-        // if has a image view, image is setted by image view, displayBlock is 
not needed
-        return nil;
+    if (_isCompositingChild) {
+        return YES;
+    } else {
+        return NO;
     }
-    
-    __weak typeof(self) weakSelf = self;
-    return ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) {
-        if (isCancelled()) {
-            return nil;
-        }
-        
-        if (!weakSelf.image) {
-            [weakSelf updateImage];
-            return nil;
-        }
-        
-        if (isCancelled && isCancelled()) {
-            return nil;
-        }
-        
-        UIGraphicsBeginImageContextWithOptions(bounds.size, self.layer.opaque, 
1.0);
-        
-        [weakSelf.image drawInRect:bounds];
-        
-        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-        
-        UIGraphicsEndImageContext();
-        
-        return image;
-    };
+}
+
+- (UIImage *)drawRect:(CGRect)rect
+{
+    if (!self.image) {
+        [self updateImage];
+    }
+    return self.image;
 }
 
 - (void)viewWillUnload
@@ -262,6 +245,9 @@ static dispatch_queue_t WXImageUpdateQueue;
                     ((UIImageView *)strongSelf.view).image = image;
                     weakSelf.imageDownloadFinish = YES;
                     [self readyToRender];
+                } else if (strongSelf->_isCompositingChild) {
+                    strongSelf->_image = image;
+                    weakSelf.imageDownloadFinish = YES;
                 }
             });
         }];
@@ -302,6 +288,10 @@ static dispatch_queue_t WXImageUpdateQueue;
                         strongSelf.imageDownloadFinish = YES;
                         ((UIImageView *)strongSelf.view).image = image;
                         [strongSelf readyToRender];
+                    } else if (strongSelf->_isCompositingChild) {
+                        strongSelf.imageDownloadFinish = YES;
+                        strongSelf->_image = image;
+                        [strongSelf setNeedsDisplay];
                     }
                 });
             }];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
index 77e7ce2..4ee3860 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
@@ -42,37 +42,6 @@
     return [WXLayer class];
 }
 
-- (UIImage *)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding
-{
-    if (bounds.size.width <=0 || bounds.size.height <= 0) {
-        return nil;
-    }
-    UIGraphicsBeginImageContextWithOptions(bounds.size, self.layer.opaque, 
WXScreenScale());
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    if ([self.wx_component _needsDrawBorder]) {
-        [self.wx_component _drawBorderWithContext:context size:bounds.size];
-    } else {
-        WXPerformBlockOnMainThread(^{
-            [self.wx_component _resetNativeBorderRadius];
-        });
-    }
-    NSLayoutManager *layoutManager = _textStorage.layoutManagers.firstObject;
-    NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
-    
-    CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding);
-    NSRange glyphRange = [layoutManager 
glyphRangeForTextContainer:textContainer];
-    
-    [layoutManager drawBackgroundForGlyphRange:glyphRange 
atPoint:textFrame.origin];
-    [layoutManager drawGlyphsForGlyphRange:glyphRange 
atPoint:textFrame.origin];
-    
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    
-    UIGraphicsEndImageContext();
-    
-    return image;
-}
-
 - (void)setTextStorage:(NSTextStorage *)textStorage
 {
     if (_textStorage != textStorage) {
@@ -227,25 +196,21 @@ do {\
     return [[WXText alloc] init];
 }
 
-- (WXDisplayBlock)displayBlock
+- (BOOL)needsDrawRect
 {
-    WXText *textView = ((WXText *)self.view);
-    return ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) {
-        if (isCancelled()) {
-            return nil;
-        }
-        if (_isUsingTextStorageLock) {
-            pthread_mutex_lock(&_textStorageMutex);
-        }
-        
-        UIImage *image = [textView drawTextWithBounds:bounds padding:_padding];
-        
-        if (_isUsingTextStorageLock) {
-            pthread_mutex_unlock(&_textStorageMutex);
-        }
-        
-        return image;
-    };
+    return YES;
+}
+
+- (UIImage *)drawRect:(CGRect)rect
+{
+    if (_isCompositingChild) {
+        [self drawTextWithBounds:rect padding:_padding view:nil];
+    } else {
+        WXText *textView = ((WXText *)self.view);
+        [self drawTextWithBounds:rect padding:_padding view:textView];
+    }
+    
+    return nil;
 }
 
 - (CGSize (^)(CGSize))measureBlock
@@ -287,6 +252,7 @@ do {\
 }
 
 #pragma mark Text Building
+
 - (NSString *)text
 {
     return _text;
@@ -447,6 +413,31 @@ do {\
     [self syncTextStorageForView];
 }
 
+- (void)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding 
view:(WXText *)view
+{
+    if (bounds.size.width <=0 || bounds.size.height <= 0) {
+        return;
+    }
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    if ([self _needsDrawBorder]) {
+        [self _drawBorderWithContext:context size:bounds.size];
+    } else {
+        WXPerformBlockOnMainThread(^{
+            [self _resetNativeBorderRadius];
+        });
+    }
+    NSLayoutManager *layoutManager = (view ? view.textStorage : 
_textStorage).layoutManagers.firstObject;
+    NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
+    
+    CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding);
+    NSRange glyphRange = [layoutManager 
glyphRangeForTextContainer:textContainer];
+    
+    [layoutManager drawBackgroundForGlyphRange:glyphRange 
atPoint:textFrame.origin];
+    [layoutManager drawGlyphsForGlyphRange:glyphRange 
atPoint:textFrame.origin];
+}
+
 #ifdef UITEST
 - (NSString *)description
 {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m 
b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
index 2231d46..fdd02a1 100644
--- a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
+++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
@@ -28,10 +28,10 @@
 {
     WXAssertMainThread();
     
-    if (_compositingChild) {
+    if (_isCompositingChild) {
         WXComponent *supercomponent = self.supercomponent;
         while (supercomponent) {
-            if (supercomponent->_composite) {
+            if (supercomponent->_useCompositing) {
                 break;
             }
             supercomponent = supercomponent.supercomponent;
@@ -44,54 +44,82 @@
     }
 }
 
-- (WXDisplayBlock)displayBlock
+- (BOOL)needsDrawRect
+{
+    if (![self _needsDrawBorder]) {
+        WXLogDebug(@"No need to draw border for %@", self.ref);
+        WXPerformBlockOnMainThread(^{
+            [self _resetNativeBorderRadius];
+        });
+        
+        return NO;
+    }
+    
+    return YES;
+}
+
+- (UIImage *)drawRect:(CGRect)rect
+{
+    CGSize size = rect.size;
+    if (size.width <= 0 || size.height <= 0) {
+        WXLogDebug(@"No need to draw border for %@, because width or height is 
zero", self.ref);
+        return nil;
+    }
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    [self _drawBorderWithContext:context size:size];
+
+    return nil;
+}
+
+- (WXDisplayBlock)_displayBlock
 {
     WXDisplayBlock displayBlock = ^UIImage *(CGRect bounds, 
BOOL(^isCancelled)(void)) {
         if (isCancelled()) {
             return nil;
         }
-        
-        if (![self _needsDrawBorder]) {
-            WXLogDebug(@"No need to draw border for %@", self.ref);
-            WXPerformBlockOnMainThread(^{
-                [self _resetNativeBorderRadius];
-            });
-            return nil;
+
+        UIGraphicsBeginImageContextWithOptions(bounds.size, [self 
_bitmapOpaqueWithSize:bounds.size] , 0.0);
+        UIImage *image = [self drawRect:bounds];
+        if (!image) {
+            image = UIGraphicsGetImageFromCurrentImageContext();
         }
+        UIGraphicsEndImageContext();
         
-        return [self _borderImage];
+        return image;
     };
     
     return displayBlock;
 }
 
-- (WXDisplayCompletionBlock)displayCompletionBlock
+#pragma mark Private
+
+- (void)_initCompositingAttribute:(NSDictionary *)attributes
 {
-    return nil;
+    _useCompositing = attributes[@"compositing"] ? [WXConvert 
BOOL:attributes[@"compositing"]] : NO;
 }
 
-#pragma mark Private
-
 - (void)_willDisplayLayer:(CALayer *)layer
 {
     WXAssertMainThread();
     
-    if (_compositingChild) {
-        // compsiting children need not draw layer
+    if (_isCompositingChild) {
+        // compsiting children do not have own layers, so return here.
         return;
     }
     
     CGRect displayBounds = CGRectMake(0, 0, self.calculatedFrame.size.width, 
self.calculatedFrame.size.height);
     
+    BOOL needsDrawRect = [self needsDrawRect];
     WXDisplayBlock displayBlock;
-    if (_composite) {
+    if (_useCompositing) {
         displayBlock = [self _compositeDisplayBlock];
     } else {
-        displayBlock = [self displayBlock];
+        displayBlock = [self _displayBlock];
     }
     WXDisplayCompletionBlock completionBlock = [self displayCompletionBlock];
     
-    if (!displayBlock) {
+    if (!displayBlock || !needsDrawRect) {
         if (completionBlock) {
             completionBlock(layer, NO);
         }
@@ -146,6 +174,22 @@
     }
 }
 
+- (CGContextRef)beginDrawContext:(CGRect)bounds
+{
+    UIGraphicsBeginImageContextWithOptions(bounds.size, [self 
_bitmapOpaqueWithSize:bounds.size], 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    return context;
+}
+
+- (UIImage *)endDrawContext
+{
+    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    
+    return image;
+}
+
 - (WXDisplayBlock)_compositeDisplayBlock
 {
     return ^UIImage* (CGRect bounds, BOOL(^isCancelled)(void)) {
@@ -153,11 +197,20 @@
             return nil;
         }
         NSMutableArray *displayBlocks = [NSMutableArray array];
-        [self _collectDisplayBlocks:displayBlocks isCancelled:isCancelled];
         
-        BOOL opaque = _layer.opaque && 
CGColorGetAlpha(_backgroundColor.CGColor) == 1.0f;
+        CGContextRef context = [self beginDrawContext:bounds];
+        
+//        float scaleFactor = [[UIScreen mainScreen] scale];
+//        CGColorSpaceRef      colorSpace = CGColorSpaceCreateDeviceRGB();
+//        CGContextRef context = CGBitmapContextCreate(NULL, bounds.size.width 
* scaleFactor, bounds.size.height * scaleFactor, 8, 4 * bounds.size.width * 
scaleFactor, colorSpace, kCGImageAlphaPremultipliedLast | 
kCGBitmapByteOrder32Big);
+//        CGContextScaleCTM(context, scaleFactor, scaleFactor);
+//        
+//        // Adjusts position and invert the image.
+//        // The OpenGL uses the image data upside-down compared commom image 
files.
+//        CGContextTranslateCTM(context, 0, bounds.size.height);
+//        CGContextScaleCTM(context, 1.0, -1.0);
         
-        UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0.0);
+        [self _collectCompositingDisplayBlocks:displayBlocks context:context 
isCancelled:isCancelled];
         
         for (dispatch_block_t block in displayBlocks) {
             if (isCancelled()) {
@@ -167,36 +220,32 @@
             block();
         }
         
-        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-        UIGraphicsEndImageContext();
+//        CGImageRef imageRef= CGBitmapContextCreateImage(context);
+//        UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
         
+//        CGColorSpaceRelease(colorSpace);
+//        CGContextRelease(context);
+       
+        UIImage *image = [self endDrawContext];
         return image;
     };
 }
 
-- (void)_collectDisplayBlocks:(NSMutableArray *)displayBlocks 
isCancelled:(BOOL(^)(void))isCancelled
+- (void)_collectCompositingDisplayBlocks:(NSMutableArray *)displayBlocks 
context:(CGContextRef)context isCancelled:(BOOL(^)(void))isCancelled
 {
-    // compositingChild has no chance to applyPropertiesToView, so force 
updateNode
-    //    if (_compositingChild) {
-    //        if (_data) {
-    //            dispatch_async(dispatch_get_main_queue(), ^{
-    //                [self updateNode:_data];
-    //            });
-    //        }
-    //    }
-    
+    // TODO: compositingChild has no chance to applyPropertiesToView, need 
update here?
     UIColor *backgroundColor = _backgroundColor;
     BOOL clipsToBounds = _clipToBounds;
     CGRect frame = self.calculatedFrame;
     CGRect bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
     
-    if (_composite) {
+    if (_useCompositing) {
         frame.origin = CGPointMake(0, 0);
     }
     
-    WXDisplayBlock displayBlock = [self displayBlock];
+    BOOL needsDrawRect = [self needsDrawRect];
     
-    BOOL shouldDisplay = displayBlock || backgroundColor || 
CGPointEqualToPoint(CGPointZero, frame.origin) == NO || clipsToBounds;
+    BOOL shouldDisplay = needsDrawRect && (backgroundColor || 
CGPointEqualToPoint(CGPointZero, frame.origin) == NO || clipsToBounds);
     
     if (shouldDisplay) {
         dispatch_block_t displayBlockToPush = ^{
@@ -204,21 +253,17 @@
             CGContextSaveGState(context);
             CGContextTranslateCTM(context, frame.origin.x, frame.origin.y);
             
-            if (_compositingChild && clipsToBounds) {
-                [[UIBezierPath bezierPathWithRect:bounds] addClip];
+            if (isCancelled && isCancelled()) {
+                return ;
             }
             
-            CGColorRef backgroundCGColor = backgroundColor.CGColor;
-            if (backgroundColor && CGColorGetAlpha(backgroundCGColor) > 0.0) {
-                CGContextSetFillColorWithColor(context, backgroundCGColor);
-                CGContextFillRect(context, bounds);
+            if (_isCompositingChild && clipsToBounds) {
+                [[UIBezierPath bezierPathWithRect:bounds] addClip];
             }
             
-            if (displayBlock) {
-                UIImage *image = displayBlock(bounds, isCancelled);
-                if (image) {
-                    [image drawInRect:bounds];
-                }
+            UIImage *image = [self drawRect:bounds];
+            if (image) {
+                [image drawInRect:bounds];
             }
         };
         [displayBlocks addObject:[displayBlockToPush copy]];
@@ -226,13 +271,12 @@
     
     for (WXComponent *component in self.subcomponents) {
         if (!isCancelled()) {
-            [component _collectDisplayBlocks:displayBlocks 
isCancelled:isCancelled];
+            [component _collectCompositingDisplayBlocks:displayBlocks 
context:context isCancelled:isCancelled];
         }
     }
     
     if (shouldDisplay) {
         dispatch_block_t blockToPop = ^{
-            CGContextRef context = UIGraphicsGetCurrentContext();
             CGContextRestoreGState(context);
         };
         [displayBlocks addObject:[blockToPop copy]];
@@ -241,26 +285,6 @@
 
 #pragma mark Border Drawing
 
-- (UIImage *)_borderImage
-{
-    CGSize size = self.calculatedFrame.size;
-    if (size.width <= 0 || size.height <= 0) {
-        WXLogDebug(@"No need to draw border for %@, because width or height is 
zero", self.ref);
-        return nil;
-    }
-    
-    WXLogDebug(@"Begin to draw border for %@", self.ref);
-    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    
-    [self _drawBorderWithContext:context size:size];
-    
-    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    
-    return image;
-}
-
 - (void)_drawBorderWithContext:(CGContextRef)context size:(CGSize)size
 {
     CGRect rect = CGRectMake(0, 0, size.width, size.height);
@@ -353,6 +377,10 @@
 
 - (BOOL)_needsDrawBorder
 {
+    if (_isCompositingChild) {
+        return YES;
+    }
+    
     if (![_layer isKindOfClass:[WXLayer class]]) {
         // Only support WXLayer
         return NO;
@@ -491,4 +519,25 @@ do {\
     }
 }
 
+- (BOOL)_bitmapOpaqueWithSize:(CGSize)size
+{
+    CGRect rect = CGRectMake(0, 0, size.width, size.height);
+    WXRoundedRect *borderRect = [[WXRoundedRect alloc] initWithRect:rect 
topLeft:_borderTopLeftRadius topRight:_borderTopRightRadius 
bottomLeft:_borderBottomLeftRadius bottomRight:_borderBottomRightRadius];
+    WXRadii *radii = borderRect.radii;
+    BOOL hasBorderRadius = [radii hasBorderRadius];
+    return (!hasBorderRadius) && CGColorGetAlpha(_backgroundColor.CGColor) == 
1.0;
+}
+
+#pragma mark - Deprecated
+
+- (WXDisplayBlock)displayBlock
+{
+    return [self _displayBlock];
+}
+
+- (WXDisplayCompletionBlock)displayCompletionBlock
+{
+    return nil;
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h 
b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h
index 9cabf8e..4cde88a 100644
--- a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h
+++ b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h
@@ -17,6 +17,8 @@
 @property (nonatomic, assign) CGFloat bottomLeft;
 @property (nonatomic, assign) CGFloat bottomRight;
 
+- (BOOL)hasBorderRadius;
+
 @end
 
 @interface WXRoundedRect : NSObject

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm 
b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm
index ae535dd..fb62465 100644
--- a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm
+++ b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm
@@ -26,6 +26,11 @@
     return self;
 }
 
+- (BOOL)hasBorderRadius
+{
+    return _topLeft > 0.001 || _topRight > 0.001 || _bottomLeft > 0.001 || 
_bottomRight > 0.001;
+}
+
 - (void)scale:(float)factor
 {
     if (factor == 1) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h 
b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
index a2f75d7..6bd7cd3 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
@@ -324,34 +324,69 @@ NS_ASSUME_NONNULL_BEGIN
 /// @name Display
 ///--------------------------------------
 
-typedef UIImage * _Nonnull(^WXDisplayBlock)(CGRect bounds, 
BOOL(^isCancelled)(void));
-typedef void(^WXDisplayCompletionBlock)(CALayer *layer, BOOL finished);
-
 /**
  * @abstract Marks the view as needing display. The method should be called on 
the main thread.
+ * @discussion You can use this method to notify the system that your 
component's contents need to be redrawn. This method makes a note of the 
request and returns immediately. The component is not actually redrawn until 
the next drawing cycle, at which point all invalidated components are updated.
+ *
  */
 - (void)setNeedsDisplay;
 
+- (CGContextRef)beginDrawContext:(CGRect)bounds;
+
+- (UIImage *)endDrawContext;
+
 /**
- * @abstract Return a block to be called to draw layer.
- *
- * @discussion The block returned will be called on any thread.
- *
+ * @abstract Returns a Boolean indicating whether the component needs to be 
drawn by `drawRect:`
+ */
+- (BOOL)needsDrawRect;
+
+/**
+ * @abstract Draws the component’s image within the passed-in rectangle.
+ * @parameter rect The rectangle which is the entire visible bounds of your 
component. 
+ * @return A UIImage containing the contents of the current bitmap graphics 
context.
+ * @discussion 
+ * Subclasses that use technologies such as Core Graphics and UIKit to draw 
their own component’s content should override this method and implement their 
drawing code there. You do not need to override this method if your component 
sets its content in superclass's way.
+ * By the time this method is called, UIKit has configured the drawing 
environment appropriately for your view and you can simply call whatever 
drawing methods and functions you need to render your content. Specifically, 
Weex creates and configures a graphics context for drawing and adjusts the 
transform of that context so that its origin matches the origin of your 
components’s bounds rectangle. You can get a reference to the graphics 
context using the `UIGraphicsGetCurrentContext` function, but do not establish 
a strong reference to the graphics context because it can change between calls 
to the drawRect: method.
+ * If you already have an image that represents the content of the component, 
then you should just return the image and do no drawing, otherwise you should 
draw your content in the current context and return nil.
+ * You should never call this method directly yourself. To invalidate part of 
your component's content, and thus cause that portion to be redrawn, call the 
`setNeedsDisplay` method instead.
+ */
+- (UIImage *)drawRect:(CGRect)rect;
+
+/**
+ * @abstract Called when a component finishes rendering its content.
+ * @discussion Do not call this method directly. Weex calls this method at 
appropriate times to finish updating the component's content.
+ * Subclasses can override this method to perform additional work on 
components that were rendered.
  */
-- (WXDisplayBlock)displayBlock;
+- (void)displayDidFinished:(BOOL)success;
 
 /**
- * readyToRender
+ * readyToRender, do not use it, will be deprecated soon
  */
 - (void)readyToRender;
 
+@end
+
+@interface WXComponent (Deprecated)
+
+typedef UIImage * _Nonnull(^WXDisplayBlock)(CGRect bounds, 
BOOL(^isCancelled)(void));
+typedef void(^WXDisplayCompletionBlock)(CALayer *layer, BOOL finished);
+
+/**
+ * @abstract Return a block to be called to draw layer.
+ *
+ * @discussion The block returned will be called on any thread.
+ *
+ */
+- (WXDisplayBlock)displayBlock DEPRECATED_MSG_ATTRIBUTE("use drawRect method 
instead.");
+
 /**
  * @abstract Return a block to be called while drawing is finished.
  *
  * @discussion The block returned will be called on main thread.
  *
  */
-- (WXDisplayCompletionBlock)displayCompletionBlock;
+- (WXDisplayCompletionBlock)displayCompletionBlock 
DEPRECATED_MSG_ATTRIBUTE("use displayDidFinished method instead.");
+
 
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m 
b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index cecc708..08a1bcc 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -95,6 +95,7 @@
         [self _setupNavBarWithStyles:_styles attributes:_attributes];
         [self _initCSSNodeWithStyles:_styles];
         [self _initViewPropertyWithStyles:_styles];
+        [self _initCompositingAttribute:_attributes];
         [self _handleBorders:styles isUpdating:NO];
     }
     
@@ -180,7 +181,7 @@
         WXAssertMainThread();
         
         // compositing child will be drew by its composited ancestor
-        if (_compositingChild) {
+        if (_isCompositingChild) {
             return nil;
         }
         
@@ -332,6 +333,10 @@
         subcomponent->_isNeedJoinLayoutSystem = NO;
     }
     
+    if (_useCompositing || _isCompositingChild) {
+        subcomponent->_isCompositingChild = YES;
+    }
+    
     [self _recomputeCSSNodeChildren];
     [self setNeedsLayout];
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m 
b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 83bcd7d..66985a9 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -292,8 +292,10 @@ typedef enum : NSUInteger {
     }
     
     [[WXSDKManager bridgeMgr] destroyInstance:self.instanceId];
-
-    [self.componentManager invalidate];
+    
+    if (_componentManager) {
+        [_componentManager invalidate];
+    }
     __weak typeof(self) weakSelf = self;
     WXPerformBlockOnComponentThread(^{
         __strong typeof(self) strongSelf = weakSelf;

Reply via email to