You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ac...@apache.org on 2018/04/26 12:39:54 UTC
[02/16] incubator-weex git commit: [WEEX-311] [iOS] use new
layoutEngin to replace yoga
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
new file mode 100644
index 0000000..0556ca5
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
@@ -0,0 +1,953 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXComponent.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKManager.h"
+#import "WXSDKInstance.h"
+#import "WXSDKInstance_private.h"
+#import "WXDefine.h"
+#import "WXLog.h"
+#import "WXWeakObjectWrapper.h"
+#import "WXUtility.h"
+#import "WXConvert.h"
+#import "WXMonitor.h"
+#import "WXAssert.h"
+#import "WXThreadSafeMutableDictionary.h"
+#import "WXThreadSafeMutableArray.h"
+#import "WXTransform.h"
+#import "WXRoundedRect.h"
+#import <pthread/pthread.h>
+#import "WXComponent+PseudoClassManagement.h"
+#import "WXComponent+BoxShadow.h"
+#import "WXTracingManager.h"
+#import "WXComponent+Events.h"
+#import "WXComponent+Layout.h"
+
+#pragma clang diagnostic ignored "-Wincomplete-implementation"
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+@interface WXComponent () <UIGestureRecognizerDelegate>
+
+@end
+
+@implementation WXComponent
+{
+@private
+ NSString *_ref;
+ NSMutableDictionary *_styles;
+ NSMutableDictionary *_attributes;
+ NSMutableArray *_events;
+
+ // Protects properties styles/attributes/events/subcomponents which will be accessed from multiple threads.
+ pthread_mutex_t _propertyMutex;
+ pthread_mutexattr_t _propertMutexAttr;
+
+ __weak WXComponent *_supercomponent;
+ __weak id<WXScrollerProtocol> _ancestorScroller;
+ __weak WXSDKInstance *_weexInstance;
+}
+
+#pragma mark Life Cycle
+
+- (instancetype)initWithRef:(NSString *)ref
+ type:(NSString *)type
+ styles:(NSDictionary *)styles
+ attributes:(NSDictionary *)attributes
+ events:(NSArray *)events
+ weexInstance:(WXSDKInstance *)weexInstance
+{
+ if (self = [super init]) {
+ pthread_mutexattr_init(&_propertMutexAttr);
+ pthread_mutexattr_settype(&_propertMutexAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&_propertyMutex, &_propertMutexAttr);
+
+ _ref = ref;
+ _type = type;
+ _weexInstance = weexInstance;
+ _componentType = WXComponentTypeCommon;
+ _styles = [self parseStyles:styles];
+ _attributes = attributes ? [NSMutableDictionary dictionaryWithDictionary:attributes] : [NSMutableDictionary dictionary];
+ _events = events ? [NSMutableArray arrayWithArray:events] : [NSMutableArray array];
+ _subcomponents = [NSMutableArray array];
+ _absolutePosition = CGPointMake(NAN, NAN);
+
+ _displayType = WXDisplayTypeBlock;
+ _isNeedJoinLayoutSystem = YES;
+ _isLayoutDirty = YES;
+ _isViewFrameSyncWithCalculated = YES;
+ _ariaHidden = nil;
+ _accessible = nil;
+ _accessibilityHintContent = nil;
+
+ _async = NO;
+
+ if (styles[kWXTransitionProperty]) {
+ _transition = [[WXTransition alloc]initWithStyles:styles];
+ }
+
+ //TODO set indicator style
+ if ([type isEqualToString:@"indicator"]) {
+ _styles[@"position"] = @"absolute";
+ if (!_styles[@"left"] && !_styles[@"right"]) {
+ _styles[@"left"] = @0.0f;
+ }
+ if (!_styles[@"top"] && !_styles[@"bottom"]) {
+ _styles[@"top"] = @0.0f;
+ }
+ }
+
+ if (attributes[@"ariaHidden"]) {
+
+ _ariaHidden = [WXConvert NSString:attributes[@"ariaHidden"]];
+ }
+ if (attributes[@"role"]) {
+ _roles = attributes[@"role"];
+ }
+ if (attributes[@"ariaLabel"]) {
+ _ariaLabel = [WXConvert NSString:attributes[@"ariaLabel"]];
+ }
+ if (attributes[@"accessible"]) {
+ _accessible = [WXConvert NSString:attributes[@"accessible"]];
+ }
+ if(attributes[@"accessibilityHint"]) {
+ _accessibilityHintContent = [WXConvert NSString:attributes[@"accessibilityHint"]];
+ }
+ if (attributes[@"groupAccessibilityChildren"]) {
+ _groupAccessibilityChildren = [WXConvert NSString:attributes[@"groupAccessibilityChildren"]];
+ }
+
+ if (attributes[@"testId"]) {
+ _testId = [WXConvert NSString:attributes[@"testId"]];
+ }
+
+#ifdef DEBUG
+ WXLogDebug(@"flexLayout -> init component: ref : %@ , styles: %@",ref,styles);
+ WXLogDebug(@"flexLayout -> init component: ref : %@ , attributes: %@",ref,attributes);
+#endif
+ [self _setupNavBarWithStyles:_styles attributes:_attributes];
+
+ [self _initCSSNodeWithStyles:_styles];
+ [self _initViewPropertyWithStyles:_styles];
+ [self _initCompositingAttribute:_attributes];
+ [self _handleBorders:styles isUpdating:NO];
+
+ }
+
+ return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ NSInteger copyId = 0;
+ @synchronized(self){
+ static NSInteger __copy = 0;
+ copyId = __copy % (1024*1024);
+ __copy++;
+ }
+ NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", (long)copyId, _isTemplate ? self.ref : self->_templateComponent.ref];
+ WXComponent *component = [[[self class] allocWithZone:zone] initWithRef:copyRef type:self.type styles:self.styles attributes:self.attributes events:self.events weexInstance:self.weexInstance];
+ if (_isTemplate) {
+ component->_templateComponent = self;
+ } else {
+ component->_templateComponent = self->_templateComponent;
+ }
+//#ifndef USE_FLEX
+ if(![WXComponent isUseFlex])
+ {
+ memcpy(component->_cssNode, self.cssNode, sizeof(css_node_t));
+ component->_cssNode->context = (__bridge void *)component;
+ }
+//#else
+ else
+ {
+ //memcpy((void*)component->_flexCssNode,self.flexCssNode,sizeof(WeexCore::WXCoreLayoutNode));
+ component->_flexCssNode->copyStyle(self.flexCssNode);
+ component->_flexCssNode->copyMeasureFunc(self.flexCssNode);
+ component->_flexCssNode->setContext((__bridge void *)component);
+ }
+//#endif
+ component->_calculatedFrame = self.calculatedFrame;
+
+ NSMutableArray *subcomponentsCopy = [NSMutableArray array];
+
+ if ([WXComponent isUseFlex]) {
+ component->_subcomponents = subcomponentsCopy;
+ NSUInteger count = [self.subcomponents count];
+ for (NSInteger i = 0 ; i < count;i++){
+ WXComponent *subcomponentCopy = [[self.subcomponents objectAtIndex:i] copy];
+ [component _insertSubcomponent:subcomponentCopy atIndex:i];
+ }
+ }else{
+ for (WXComponent *subcomponent in self.subcomponents) {
+ WXComponent *subcomponentCopy = [subcomponent copy];
+ subcomponentCopy->_supercomponent = component;
+ [subcomponentsCopy addObject:subcomponentCopy];
+ }
+ component->_subcomponents = subcomponentsCopy;
+ }
+
+ WXPerformBlockOnComponentThread(^{
+ [self.weexInstance.componentManager addComponent:component toIndexDictForRef:copyRef];
+ });
+
+ return component;
+}
+
+- (UIAccessibilityTraits)_parseAccessibilityTraitsWithTraits:(UIAccessibilityTraits)trait roles:(NSString*)roleStr
+{
+ UIAccessibilityTraits newTrait = trait;
+ for (NSString * role in [roleStr componentsSeparatedByString:@" "]) {
+ newTrait |= [WXConvert WXUIAccessibilityTraits: role];
+ }
+
+ return newTrait;
+}
+
+- (void)dealloc
+{
+//#ifndef USE_FLEX
+ if(![WXComponent isUseFlex])
+ {
+ free_css_node(_cssNode);
+ }
+//#else
+ else
+ {
+ if(self.flexCssNode){
+#ifdef DEBUG
+ WXLogDebug(@"flexLayout -> dealloc %@",self.ref);
+#endif
+ delete self.flexCssNode;
+ }
+ }
+//#endif
+
+ // remove all gesture and all
+ if (_isTemplate && self.attributes[@"@templateId"]) {
+ [[WXSDKManager bridgeMgr] callComponentHook:_weexInstance.instanceId componentId:self.attributes[@"@templateId"] type:@"lifecycle" hook:@"destroy" args:nil competion:nil];
+ }
+ if (_tapGesture) {
+ [_tapGesture removeTarget:nil action:NULL];
+ }
+ if ([_swipeGestures count]) {
+ for (UISwipeGestureRecognizer *swipeGestures in _swipeGestures) {
+ [swipeGestures removeTarget:nil action:NULL];
+ }
+ }
+
+ if (_longPressGesture) {
+ [_longPressGesture removeTarget:nil action:NULL];
+ }
+
+ if (_panGesture) {
+ [_panGesture removeTarget:nil action:NULL];
+ }
+
+ if (_positionType == WXPositionTypeFixed) {
+ [self.weexInstance.componentManager removeFixedComponent:self];
+ }
+
+ pthread_mutex_destroy(&_propertyMutex);
+ pthread_mutexattr_destroy(&_propertMutexAttr);
+
+}
+
+- (NSDictionary *)styles
+{
+ NSDictionary *styles;
+ pthread_mutex_lock(&_propertyMutex);
+ styles = _styles;
+ pthread_mutex_unlock(&_propertyMutex);
+ return styles;
+}
+
+- (NSDictionary *)pseudoClassStyles
+{
+ NSDictionary *pseudoClassStyles;
+ pthread_mutex_lock(&_propertyMutex);
+ pseudoClassStyles = _pseudoClassStyles;
+ pthread_mutex_unlock(&_propertyMutex);
+
+ return pseudoClassStyles;
+}
+
+- (NSString *)type
+{
+ return _type;
+}
+
+- (NSDictionary *)attributes
+{
+ NSDictionary *attributes;
+ pthread_mutex_lock(&_propertyMutex);
+ attributes = _attributes;
+ pthread_mutex_unlock(&_propertyMutex);
+
+ return attributes;
+}
+
+- (NSArray *)events
+{
+ NSArray *events;
+ pthread_mutex_lock(&_propertyMutex);
+ events = [_events copy];
+ pthread_mutex_unlock(&_propertyMutex);
+
+ return events;
+}
+
+- (void)setDisplayType:(WXDisplayType)displayType
+{
+ if (_displayType != displayType) {
+ _displayType = displayType;
+ if (displayType == WXDisplayTypeNone) {
+ _isNeedJoinLayoutSystem = NO;
+ [self.supercomponent _recomputeCSSNodeChildren];
+ WXPerformBlockOnMainThread(^{
+ [self removeFromSuperview];
+ });
+ } else {
+ _isNeedJoinLayoutSystem = YES;
+ [self.supercomponent _recomputeCSSNodeChildren];
+ WXPerformBlockOnMainThread(^{
+ [self _buildViewHierarchyLazily];
+ // TODO: insert into the correct index
+ [self.supercomponent.view addSubview:self.view];
+ });
+ }
+ [self setNeedsLayout];
+ }
+}
+
+- (WXSDKInstance *)weexInstance
+{
+ return _weexInstance;
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@:%p ref=%@> %@", _type, self, _ref, _view];
+}
+
+#pragma mark Property
+
+- (UIView *)view
+{
+ if (_componentType != WXComponentTypeCommon) {
+ return nil;
+ }
+ if ([self isViewLoaded]) {
+ return _view;
+ } else {
+ WXAssertMainThread();
+
+ // compositing child will be drew by its composited ancestor
+ if (_isCompositingChild) {
+ return nil;
+ }
+
+ [self viewWillLoad];
+
+ _view = [self loadView];
+#ifdef DEBUG
+ WXLogDebug(@"flexLayout -> loadView:addr-(%p),componentRef-(%@)",_view,self.ref);
+#endif
+ _layer = _view.layer;
+ _view.frame = [self _fixIllegalFrame:_calculatedFrame];
+ _view.hidden = _visibility == WXVisibilityShow ? NO : YES;
+ _view.clipsToBounds = _clipToBounds;
+ if (![self _needsDrawBorder]) {
+ _layer.borderColor = _borderTopColor.CGColor;
+ _layer.borderWidth = _borderTopWidth;
+ [self _resetNativeBorderRadius];
+ _layer.opacity = _opacity;
+ _view.backgroundColor = _backgroundColor;
+ }
+
+ if (_backgroundImage) {
+ [self setGradientLayer];
+ }
+
+ if (_transform) {
+ [_transform applyTransformForView:_view];
+ }
+
+ if (_boxShadow) {
+ [self configBoxShadow:_boxShadow];
+ }
+
+ _view.wx_component = self;
+ _view.wx_ref = self.ref;
+ _layer.wx_component = self;
+
+ if (_roles) {
+ [_view setAccessibilityTraits:[self _parseAccessibilityTraitsWithTraits:self.view.accessibilityTraits roles:_roles]];
+ }
+
+ if (_testId) {
+ _view.accessibilityIdentifier = _testId;
+ }
+
+ if (_accessibilityHintContent) {
+ [_view setAccessibilityHint:_accessibilityHintContent];
+ }
+
+ if (_ariaLabel) {
+ _view.accessibilityLabel = _ariaLabel;
+ }
+ if (_accessible) {
+ [_view setIsAccessibilityElement:[WXConvert BOOL:_accessible]];
+ }
+
+ if (_ariaHidden) {
+ [_view setAccessibilityElementsHidden:[WXConvert BOOL:_ariaHidden]];
+ }
+ if (_groupAccessibilityChildren) {
+ [_view setShouldGroupAccessibilityChildren:[WXConvert BOOL:_groupAccessibilityChildren]];
+ }
+
+ [self _initEvents:self.events];
+ [self _initPseudoEvents:_isListenPseudoTouch];
+
+ if (_positionType == WXPositionTypeSticky) {
+ [self.ancestorScroller addStickyComponent:self];
+ }
+
+ if (self.supercomponent && self.supercomponent->_async) {
+ self->_async = YES;
+ }
+
+ [self setNeedsDisplay];
+ [[NSNotificationCenter defaultCenter] postNotificationName:WX_COMPONENT_NOTIFICATION_VIEW_LOADED object:self];
+ [self viewDidLoad];
+
+ if (_lazyCreateView) {
+ [self _buildViewHierarchyLazily];
+ }
+
+ [self _handleFirstScreenTime];
+
+ return _view;
+ }
+}
+
+- (CGRect)_fixIllegalFrame:(CGRect)frame{
+ CGPoint origin = frame.origin;
+ CGSize size = frame.size;
+ CGRect fixedFrame = CGRectMake(isnan(origin.x)?0.0f:origin.x
+ , isnan(origin.y)?0.0f:origin.y
+ , isnan(size.width)?0.0f:size.width
+ , isnan(size.height)?0.0f:size.height);
+ return fixedFrame;
+}
+
+- (void)_buildViewHierarchyLazily
+{
+ if (self.supercomponent && !((WXComponent *)self.supercomponent)->_lazyCreateView) {
+ NSArray *subcomponents = ((WXComponent *)self.supercomponent).subcomponents;
+
+ NSInteger index = [subcomponents indexOfObject:self];
+ if (index != NSNotFound) {
+ [(WXComponent *)self.supercomponent insertSubview:self atIndex:index];
+ }
+ }
+
+ NSArray *subcomponents = self.subcomponents;
+ for (int i = 0; i < subcomponents.count; i++) {
+ WXComponent *subcomponent = subcomponents[i];
+ [self insertSubview:subcomponent atIndex:i];
+ }
+}
+
+- (void)_resetNativeBorderRadius
+{
+ WXRoundedRect *borderRect = [[WXRoundedRect alloc] initWithRect:_calculatedFrame topLeft:_borderTopLeftRadius topRight:_borderTopRightRadius bottomLeft:_borderBottomLeftRadius bottomRight:_borderBottomRightRadius];
+ _layer.cornerRadius = borderRect.radii.topLeft;
+}
+
+- (void)_handleFirstScreenTime
+{
+ if (WX_MONITOR_INSTANCE_PERF_IS_RECORDED(WXPTFirstScreenRender, self.weexInstance)) {
+ return;
+ }
+ CGPoint absolutePosition = [self.supercomponent.view convertPoint:_view.frame.origin toView:_weexInstance.rootView];
+ if (absolutePosition.y + _view.frame.size.height > self.weexInstance.rootView.frame.size.height + 1) {
+ WX_MONITOR_INSTANCE_PERF_END(WXPTFirstScreenRender, self.weexInstance);
+ }
+}
+
+- (CALayer *)layer
+{
+ return _layer;
+}
+
+- (CGRect)calculatedFrame
+{
+ return _calculatedFrame;
+}
+
+- (CGPoint)absolutePosition
+{
+ return _absolutePosition;
+}
+
+//#ifndef USE_FLEX
+- (css_node_t *)cssNode
+{
+ return _cssNode;
+}
+//#else
+//#endif
+
+- (void)_addEventParams:(NSDictionary *)params
+{
+ pthread_mutex_lock(&_propertyMutex);
+ if (!_eventParameters) {
+ _eventParameters = [NSMutableDictionary dictionary];
+ }
+ [_eventParameters addEntriesFromDictionary:params];
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (NSArray *)_paramsForEvent:(NSString *)eventName
+{
+ NSArray *params;
+ pthread_mutex_lock(&_propertyMutex);
+ params = _eventParameters[eventName];
+ pthread_mutex_unlock(&_propertyMutex);
+
+ return params;
+}
+
+#pragma mark Component Hierarchy
+
+- (NSArray<WXComponent *> *)subcomponents
+{
+ NSArray<WXComponent *> *subcomponents;
+ pthread_mutex_lock(&_propertyMutex);
+ subcomponents = [_subcomponents copy];
+ pthread_mutex_unlock(&_propertyMutex);
+
+ return subcomponents;
+}
+
+- (WXComponent *)supercomponent
+{
+ return _supercomponent;
+}
+
+- (void)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index
+{
+ WXAssert(subcomponent, @"The subcomponent to insert to %@ at index %d must not be nil", self, index);
+ if (index > [_subcomponents count]) {
+ WXLogError(@"the index of inserted %ld is out of range as the current is %lu", (long)index, (unsigned long)[_subcomponents count]);
+ return;
+ }
+
+ subcomponent->_supercomponent = self;
+
+ pthread_mutex_lock(&_propertyMutex);
+ [_subcomponents insertObject:subcomponent atIndex:index];
+ pthread_mutex_unlock(&_propertyMutex);
+
+ if (subcomponent->_positionType == WXPositionTypeFixed) {
+ [self.weexInstance.componentManager addFixedComponent:subcomponent];
+ subcomponent->_isNeedJoinLayoutSystem = NO;
+ }
+
+ if (_useCompositing || _isCompositingChild) {
+ subcomponent->_isCompositingChild = YES;
+ }
+//#ifndef USE_FLEX
+ if(![WXComponent isUseFlex])
+ {
+
+ }
+//#else
+ else
+ {
+ if (subcomponent->_isNeedJoinLayoutSystem) {
+ NSInteger actualIndex = [self getActualNodeIndex:subcomponent atIndex:index];
+ [self _insertChildCssNode:subcomponent atIndex:actualIndex];
+ }else{
+#ifdef DEBUG
+ WXLogDebug(@"flexLayout -> no need JoinLayoutSystem parent ref:%@ type:%@, self ref:%@ type:%@ ",
+ self.ref,
+ self.type,
+ subcomponent.ref,
+ subcomponent.type
+ );
+#endif
+ }
+ }
+//#endif
+
+ [self _recomputeCSSNodeChildren];
+ [self setNeedsLayout];
+}
+
+- (void)_removeSubcomponent:(WXComponent *)subcomponent
+{
+ pthread_mutex_lock(&_propertyMutex);
+ [_subcomponents removeObject:subcomponent];
+//#ifndef USE_FLEX
+ if (![WXComponent isUseFlex]) {
+ }
+//#else
+ else
+ {
+ //subcomponent->_isNeedJoinLayoutSystem = NO;
+ [self _rmChildCssNode:subcomponent];
+ }
+//#endif
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (void)_removeFromSupercomponent
+{
+ [self.supercomponent _removeSubcomponent:self];
+ [self.supercomponent _recomputeCSSNodeChildren];
+ [self.supercomponent setNeedsLayout];
+
+ if (_positionType == WXPositionTypeFixed) {
+ [self.weexInstance.componentManager removeFixedComponent:self];
+ self->_isNeedJoinLayoutSystem = YES;
+ }
+}
+
+- (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index
+{
+ [self _removeFromSupercomponent];
+ [newSupercomponent _insertSubcomponent:self atIndex:index];
+}
+
+- (void)_didInserted
+{
+
+}
+
+- (id<WXScrollerProtocol>)ancestorScroller
+{
+ if(!_ancestorScroller) {
+ WXComponent *supercomponent = self.supercomponent;
+ while (supercomponent) {
+ if([supercomponent conformsToProtocol:@protocol(WXScrollerProtocol)]) {
+ _ancestorScroller = (id<WXScrollerProtocol>)supercomponent;
+ break;
+ }
+ supercomponent = supercomponent.supercomponent;
+ }
+ }
+
+ return _ancestorScroller;
+}
+
+#pragma mark Updating
+- (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles
+{
+ NSLog(@"tempTest updating");
+
+ BOOL isTransitionTag = _transition ? [self _isTransitionTag:styles] : NO;
+ if (isTransitionTag) {
+ [_transition _handleTransitionWithStyles:styles resetStyles:resetStyles target:self];
+ } else {
+ styles = [self parseStyles:styles];
+ [self _updateCSSNodeStyles:styles];
+ [self _resetCSSNodeStyles:resetStyles];
+ }
+ if (isUpdateStyles) {
+ [self _modifyStyles:styles];
+ if ([self needsLayout]) {
+ // call update style may take effect on layout, maybe the component
+ // displaylink has been paused, so we need to restart the component task, and it will auto-pause when task queue is empty.
+ [self.weexInstance.componentManager startComponentTasks];
+ }
+ }
+}
+
+- (BOOL)_isTransitionTag:(NSDictionary *)styles
+{
+ BOOL yesOrNo = false;
+ if (_transition.transitionOptions != WXTransitionOptionsNone) {
+ yesOrNo = true;
+ }
+ return yesOrNo;
+}
+
+- (BOOL)_isTransitionOnMainThreadStyles:(NSDictionary *)styles
+{
+ BOOL yesOrNo = false;
+ if (_transition.transitionOptions != WXTransitionOptionsNone) {
+ if ((_transition.transitionOptions & WXTransitionOptionsBackgroundColor &&styles[@"backgroundColor"])
+ ||(_transition.transitionOptions & WXTransitionOptionsTransform &&styles[@"transform"])
+ ||(_transition.transitionOptions & WXTransitionOptionsOpacity &&styles[@"opacity"])) {
+ yesOrNo = true;
+ }
+ }
+ return yesOrNo;
+}
+
+- (void)_modifyStyles:(NSDictionary *)styles
+{
+ pthread_mutex_lock(&_propertyMutex);
+ [_styles addEntriesFromDictionary:styles];
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes
+{
+ pthread_mutex_lock(&_propertyMutex);
+ [_attributes addEntriesFromDictionary:attributes];
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (void)_addEventOnComponentThread:(NSString *)eventName
+{
+ pthread_mutex_lock(&_propertyMutex);
+ [_events addObject:eventName];
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (void)_removeEventOnComponentThread:(NSString *)eventName
+{
+ pthread_mutex_lock(&_propertyMutex);
+ [_events removeObject:eventName];
+ pthread_mutex_unlock(&_propertyMutex);
+}
+
+- (void)_updateStylesOnMainThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles
+{
+ WXAssertMainThread();
+ if (![self _isTransitionOnMainThreadStyles:styles]) {
+ [self _updateViewStyles:styles];
+ } else {
+ [self _transitionUpdateViewProperty:styles];
+ }
+#ifdef DEBUG
+ NSDictionary *copySelfStyle = [NSDictionary dictionaryWithDictionary:self.styles];
+ WXLogDebug(@"flexLayout -> ref:%@ style before : %@",self.ref,copySelfStyle);
+
+ if (styles) {
+ WXLogDebug(@"flexLayout -> ref:%@ update styles : %@",self.ref,styles);
+ }
+
+ if (resetStyles) {
+ WXLogDebug(@"flexLayout -> ref:%@ update resetStyles : %@",self.ref,resetStyles);
+ }
+#endif
+
+ [self _resetStyles:resetStyles];
+ [self _handleBorders:styles isUpdating:YES];
+ [self updateStyles:styles];
+ [self resetStyles:resetStyles];
+
+#ifdef DEBUG
+ //self.styles may change
+ copySelfStyle = [NSDictionary dictionaryWithDictionary:self.styles];
+ WXLogDebug(@"flexLayout -> ref:%@ style after : %@",self.ref,copySelfStyle);
+#endif
+}
+
+- (void)_updateAttributesOnMainThread:(NSDictionary *)attributes
+{
+ WXAssertMainThread();
+
+ [self _updateNavBarAttributes:attributes];
+
+ [self updateAttributes:attributes];
+ [self _configWXComponentA11yWithAttributes:attributes];
+}
+
+- (void)updateStyles:(NSDictionary *)styles
+{
+ WXAssertMainThread();
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+ WXAssertMainThread();
+}
+
+- (void)setNativeTransform:(CGAffineTransform)transform
+{
+ WXAssertMainThread();
+
+ _transform = [[WXTransform alloc] initWithNativeTransform:CATransform3DMakeAffineTransform(transform) instance:self.weexInstance];
+ if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) {
+ [_transform applyTransformForView:_view];
+ [_layer setNeedsDisplay];
+ }
+}
+
+- (void)readyToRender
+{
+ if (self.weexInstance.trackComponent) {
+ [self.supercomponent readyToRender];
+ }
+}
+
+
+- (void)setGradientLayer
+{
+ if (CGRectEqualToRect(self.view.frame, CGRectZero)) {
+ return;
+ }
+ NSDictionary * linearGradient = [WXUtility linearGradientWithBackgroundImage:_backgroundImage];
+ if (!linearGradient) {
+ return ;
+ }
+
+ __weak typeof(self) weakSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ __strong typeof(self) strongSelf = weakSelf;
+ if(strongSelf) {
+ UIColor * startColor = (UIColor*)linearGradient[@"startColor"];
+ UIColor * endColor = (UIColor*)linearGradient[@"endColor"];
+ CAGradientLayer * gradientLayer = [WXUtility gradientLayerFromColors:@[startColor, endColor] locations:nil frame:strongSelf.view.bounds gradientType:(WXGradientType)[linearGradient[@"gradientType"] integerValue]];
+ if (gradientLayer) {
+ _backgroundColor = [UIColor colorWithPatternImage:[strongSelf imageFromLayer:gradientLayer]];
+ strongSelf.view.backgroundColor = _backgroundColor;
+ }
+ }
+ });
+}
+
+- (void)_configWXComponentA11yWithAttributes:(NSDictionary *)attributes
+{
+ WX_CHECK_COMPONENT_TYPE(self.componentType)
+ if (attributes[@"role"]){
+ _roles = attributes[@"role"];
+ [self.view setAccessibilityTraits:[self _parseAccessibilityTraitsWithTraits:self.view.accessibilityTraits roles:_roles]];
+ }
+ if (attributes[@"ariaHidden"]) {
+ _ariaHidden = [WXConvert NSString:attributes[@"ariaHidden"]];
+ [self.view setAccessibilityElementsHidden:[WXConvert BOOL:_ariaHidden]];
+ }
+ if (attributes[@"accessible"]) {
+ _accessible = [WXConvert NSString:attributes[@"accessible"]];
+ [self.view setIsAccessibilityElement:[WXConvert BOOL:_accessible]];
+ }
+ if (attributes[@"ariaLabel"]) {
+ _ariaLabel = [WXConvert NSString:attributes[@"ariaLabel"]];
+ self.view.accessibilityValue = _ariaLabel;
+ }
+ if (attributes[@"accessibilityHint"]) {
+ _accessibilityHintContent = [WXConvert NSString:attributes[@"accessibilityHint"]];
+ [self.view setAccessibilityHint:_accessibilityHintContent];
+ }
+
+ if (attributes[@"groupAccessibilityChildren"]) {
+ _groupAccessibilityChildren = [WXConvert NSString:attributes[@"groupAccessibilityChildren"]];
+ [self.view setShouldGroupAccessibilityChildren:[WXConvert BOOL:_groupAccessibilityChildren]];
+ }
+
+
+ if (attributes[@"testId"]) {
+ [self.view setAccessibilityIdentifier:[WXConvert NSString:attributes[@"testId"]]];
+ }
+
+}
+
+- (UIImage *)imageFromLayer:(CALayer *)layer
+{
+ UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0);
+ [layer renderInContext:UIGraphicsGetCurrentContext()];
+ UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return outputImage;
+}
+
+#pragma mark Reset
+- (void)resetStyles:(NSArray *)styles
+{
+ WXAssertMainThread();
+}
+
+#pragma mark Layout
+
+/**
+ * @see WXComponent+Layout.m
+ */
+
+#pragma mark View Management
+
+/**
+ * @see WXComponent+ViewManagement.m
+ */
+
+#pragma mark Events
+
+/**
+ * @see WXComponent+Events.m
+ */
+
+#pragma mark Display
+
+/**
+ * @see WXComponent+Display.m
+ */
+
+@end
+
+
+@implementation UIView (WXComponent)
+
+- (WXComponent *)wx_component
+{
+ WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_component));
+ return [weakWrapper weakObject];
+}
+
+- (void)setWx_component:(WXComponent *)wx_component
+{
+ id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_component];
+ objc_setAssociatedObject(self, @selector(wx_component), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSString *)wx_ref
+{
+ WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_ref));
+ return [weakWrapper weakObject];
+}
+
+- (void)setWx_ref:(NSString *)wx_ref
+{
+ id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_ref];
+ objc_setAssociatedObject(self, @selector(wx_ref), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
+
+@implementation CALayer (WXComponents_new)
+
+- (WXComponent *)wx_component
+{
+ WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_component));
+ return [weakWrapper weakObject];
+}
+
+- (void)setWx_component:(WXComponent *)wx_component
+{
+ id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_component];
+ objc_setAssociatedObject(self, @selector(wx_component), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/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 13fc4cf..b4c5a2e 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -76,7 +76,8 @@ typedef enum : NSUInteger {
BOOL _needDestroy;
BOOL _syncDestroyComponentManager;
BOOL _debugJS;
- id<WXBridgeProtocol> _instanceJavaScriptContext; // sandbox javaScript context
+ id<WXBridgeProtocol> _instanceJavaScriptContext; // sandbox javaScript context
+ CGFloat _defaultPixelScaleFactor;
}
- (void)dealloc
@@ -102,7 +103,7 @@ typedef enum : NSUInteger {
__instance++;
}
_instanceId = [NSString stringWithFormat:@"%ld", (long)instanceId];
-
+
[WXSDKManager storeInstance:self forID:_instanceId];
_bizType = @"";
@@ -122,6 +123,7 @@ typedef enum : NSUInteger {
if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) {
_syncDestroyComponentManager = [[configCenter configForKey:@"iOS_weex_ext_config.syncDestroyComponentManager" defaultValue:@(YES) isDefault:NULL] boolValue];
}
+ _defaultPixelScaleFactor = CGFLOAT_MIN;
[self addObservers];
}
@@ -183,6 +185,9 @@ typedef enum : NSUInteger {
- (void)setFrame:(CGRect)frame
{
+#ifdef DEBUG
+ WXLogDebug(@"flexLayout -> setFrame :%@,instance :%@",NSStringFromCGRect(frame),self);
+#endif
if (!CGRectEqualToRect(frame, _frame)) {
_frame = frame;
WXPerformBlockOnMainThread(^{
@@ -583,7 +588,12 @@ typedef enum : NSUInteger {
if (self.viewportWidth > 0) {
return [WXUtility portraitScreenSize].width / self.viewportWidth;
} else {
- return [WXUtility defaultPixelScaleFactor];
+ if (_defaultPixelScaleFactor != CGFLOAT_MIN) {
+ return _defaultPixelScaleFactor;
+ }
+
+ _defaultPixelScaleFactor = [WXUtility defaultPixelScaleFactor];
+ return _defaultPixelScaleFactor;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Module/WXTransition.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.m b/ios/sdk/WeexSDK/Sources/Module/WXTransition.m
deleted file mode 100644
index 8e982ac..0000000
--- a/ios/sdk/WeexSDK/Sources/Module/WXTransition.m
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#define SOLVE_EPS(dur) (1. / (1000. * (dur)))
-
-#import <QuartzCore/CATransaction.h>
-#import <QuartzCore/CADisplayLink.h>
-#import "WXComponentManager.h"
-#import "WXSDKInstance.h"
-#import "WXComponent+Layout.h"
-#import "WXComponent_internal.h"
-#import "WXTransition.h"
-#import "WXUtility.h"
-#import "WXAssert.h"
-#import "WXSDKInstance_private.h"
-#import "WXLength.h"
-
-@implementation WXTransitionInfo
-@end
-
-@interface WXTransition()
-{
- WXComponent *_targetComponent;
- double ax;
- double bx;
- double cx;
-
- double ay;
- double by;
- double cy;
-
- float _transitionDuration;
- float _transitionDelay;
- NSUInteger _transitionCount;
-
- CAMediaTimingFunction *_transitionTimingFunction;
- CADisplayLink *_transitionDisplayLink;
-
- NSMutableDictionary *_filterStyles;
- NSMutableDictionary *_oldFilterStyles;
-}
-
-@end
-
-@implementation WXTransition
-
-- (instancetype)initWithStyles:(NSDictionary *)styles
-{
- if (self = [super init]) {
- NSString *property = styles[kWXTransitionProperty];
- NSArray *properties = [property componentsSeparatedByString:@","];
- for (NSString *string in properties) {
- _transitionOptions |= [self transitionOptionsFromString:string];
- }
- }
- return self;
-}
-
-#pragma mark - HandleStyle
-- (WXTransitionOptions)transitionOptionsFromString:(NSString *)string
-{
- NSDictionary<NSString*,NSNumber*> *options = @{
- @"width": @(WXTransitionOptionsWidth),
- @"height": @(WXTransitionOptionsHeight),
- @"right": @(WXTransitionOptionsRight),
- @"left": @(WXTransitionOptionsLeft),
- @"bottom": @(WXTransitionOptionsBottom),
- @"top": @(WXTransitionOptionsTop),
- @"backgroundColor": @(WXTransitionOptionsBackgroundColor),
- @"transform": @(WXTransitionOptionsTransform),
- @"opacity": @(WXTransitionOptionsOpacity),
- };
- return options[string].integerValue;
-}
-
-- (void)_handleTransitionWithStyles:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles target:(WXComponent *)targetComponent
-{
- BOOL isRunning = [self _isTransitionRunning];
- if (isRunning) {
- [self _rollBackTransitionWithStyles:styles];
- }
- else
- {
- [self _suspendTransitionDisplayLink];
- }
-
- _filterStyles = _filterStyles ?:[NSMutableDictionary new];
- _oldFilterStyles = _oldFilterStyles ?: [NSMutableDictionary new];
- NSMutableDictionary *futileStyles = [NSMutableDictionary new];
-
- for (NSString *key in styles) {
- if (self.transitionOptions & [self transitionOptionsFromString:key]) {
- [_filterStyles setObject:styles[key] forKey:key];
- if (![key isEqualToString:@"transform"]) {
- if (!isRunning) {
- [_oldFilterStyles setObject:targetComponent.styles[key] forKey:key];
- }
- }
- }
- else
- {
- [futileStyles setObject:styles[key] forKey:key];
- }
- }
- [self updateFutileStyles:futileStyles resetStyles:nil target:targetComponent];
-
- _targetComponent = targetComponent;
- NSMutableDictionary *componentStyles = [NSMutableDictionary dictionaryWithDictionary:styles];
- [componentStyles addEntriesFromDictionary:targetComponent.styles];
-
- _transitionDuration = componentStyles[kWXTransitionDuration] ? [WXConvert CGFloat:componentStyles[kWXTransitionDuration]] : 0;
- _transitionDelay = componentStyles[kWXTransitionDelay] ? [WXConvert CGFloat:componentStyles[kWXTransitionDelay]] : 0;
- _transitionTimingFunction = [WXConvert CAMediaTimingFunction:componentStyles[kWXTransitionTimingFunction]];
-
- if (_transitionDuration == 0 ) {
- [self updateFutileStyles:_filterStyles resetStyles:nil target:targetComponent];
- return;
- }
-
- if (![[NSString stringWithFormat:@"%@",_transitionTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) {
- float vec[4] = {0.};
- [_transitionTimingFunction getControlPointAtIndex:1 values:&vec[0]];
- [_transitionTimingFunction getControlPointAtIndex:2 values:&vec[2]];
- [self unitBezierp1x:vec[0] p1y:vec[1] p2x:vec[2] p2y:vec[3]];
- }
-
- [self _resloveTransitionProperty];
- [self performSelector:@selector(_startTransitionDisplayLink) withObject:self afterDelay:_transitionDelay/1000];
-}
-
-- (void)updateFutileStyles:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles target:(WXComponent *)targetComponent
-{
- [targetComponent _updateCSSNodeStyles:styles];
- [targetComponent _resetCSSNodeStyles:resetStyles];
- WXPerformBlockOnMainThread(^{
- [targetComponent _updateViewStyles:styles];
- });
-}
-
-- (void)_rollBackTransitionWithStyles:(NSDictionary *)styles
-{
- _transitionDuration = _transitionCount * 1000 / 60;
- _transitionCount = 0;
- _propertyArray = nil;
-}
-
-- (void)_resloveTransitionProperty
-{
- if (_filterStyles.count == 0) {
- return;
- }
- for (NSString * name in _filterStyles.allKeys) {
- [self _dealTransitionWithProperty:name];
- }
-}
-
-- (void)_dealTransitionWithProperty:(NSString *)singleProperty
-{
- if (_filterStyles[singleProperty])
- {
- if (!_propertyArray) {
- _propertyArray = [NSMutableArray new];
- }
- if ([singleProperty isEqualToString:@"backgroundColor"]) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.fromValue = [self _dealWithColor:[WXConvert UIColor:_oldFilterStyles[singleProperty]]];
- info.toValue = [self _dealWithColor:[WXConvert UIColor:_filterStyles[singleProperty]]];
- info.perValue = [self _calculatePerColorRGB1:info.toValue RGB2:info.fromValue];
- info.propertyName = singleProperty;
- [_propertyArray addObject:info];
- }
- else if ([singleProperty isEqualToString:@"transform"]) {
- NSString *transformOrigin = _filterStyles[@"transformOrigin"];
- WXTransform *wxTransform = [[WXTransform alloc] initWithCSSValue:_filterStyles[singleProperty] origin:transformOrigin instance:_targetComponent.weexInstance];
- WXTransform *oldTransform = _targetComponent->_transform;
- if (wxTransform.rotateAngle != oldTransform.rotateAngle) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.rotation";
- info.fromValue = @(oldTransform.rotateAngle);
- info.toValue = [NSNumber numberWithDouble:wxTransform.rotateAngle];
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.rotateX != oldTransform.rotateX)
- {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.rotation.x";
- info.fromValue = @(oldTransform.rotateX);
- info.toValue = [NSNumber numberWithDouble:wxTransform.rotateX];
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.rotateY != oldTransform.rotateY)
- {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.rotation.y";
- info.fromValue = @(oldTransform.rotateY);
- info.toValue = [NSNumber numberWithDouble:wxTransform.rotateY];
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.rotateZ != oldTransform.rotateZ)
- {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.rotation.z";
- info.fromValue = @(oldTransform.rotateZ);
- info.toValue = [NSNumber numberWithDouble:wxTransform.rotateZ];
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.scaleX != oldTransform.scaleX) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.scale.x";
- info.fromValue = @(oldTransform.scaleX);
- info.toValue = @(wxTransform.scaleX);
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.scaleY != oldTransform.scaleY) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.scale.y";
- info.fromValue = @(oldTransform.scaleY);
- info.toValue = @(wxTransform.scaleY);
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.translateX && [wxTransform.translateX floatValue] !=[oldTransform.translateX floatValue]) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.translation.x";
- info.fromValue = @([oldTransform.translateX floatValue]);
- info.toValue = @([wxTransform.translateX floatValue]);
- info.perValue = @([wxTransform.translateX floatValue] - [oldTransform.translateX floatValue]);
- [_propertyArray addObject:info];
- }
- if (wxTransform.translateY && [wxTransform.translateY floatValue] !=[oldTransform.translateY floatValue]) {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.propertyName = @"transform.translation.y";
- info.fromValue = @([oldTransform.translateY floatValue]);
- info.toValue = @([wxTransform.translateY floatValue]);
- info.perValue = @([wxTransform.translateY floatValue] - [oldTransform.translateY floatValue]);
- [_propertyArray addObject:info];
- }
- _targetComponent->_transform = wxTransform;
- }
- else
- {
- WXTransitionInfo *info = [WXTransitionInfo new];
- info.fromValue = @(_oldFilterStyles[singleProperty] ? [WXConvert CGFloat:_oldFilterStyles[singleProperty]] : 0);
- info.toValue = @(_filterStyles[singleProperty] ? [WXConvert CGFloat:_filterStyles[singleProperty]] : 0 );
- info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
- info.propertyName = singleProperty;
- [_propertyArray addObject:info];
- }
- }
-}
-
-- (NSArray *)_dealWithColor:(UIColor *)color
-{
- CGFloat R, G, B, A;
- [color getRed:&R green:&G blue:&B alpha:&A];
- return @[@(R),@(G),@(B),@(A)];
-}
-
-- (NSArray *)_calculatePerColorRGB1:(NSArray *)RGB1 RGB2:(NSArray *)RGB2
-{
- CGFloat R = [RGB1[0] doubleValue] - [RGB2[0] doubleValue];
- CGFloat G = [RGB1[1] doubleValue] - [RGB2[1] doubleValue];
- CGFloat B = [RGB1[2] doubleValue] - [RGB2[2] doubleValue];
- CGFloat A = [RGB1[3] doubleValue] - [RGB2[3] doubleValue];
- return @[@(R),@(G),@(B),@(A)];
-}
-
-- (void)_calculatetransitionProcessingStyle
-{
- if (_propertyArray.count == 0) {
- return;
- }
- double per = 1000 * (_transitionCount + 1 ) / (60 * _transitionDuration);//linear
- if (![[NSString stringWithFormat:@"%@",_transitionTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) {
- per = [self solveWithx:((_transitionCount+2)*16)/_transitionDuration epsilon:SOLVE_EPS(_transitionDuration)];
- }
- NSString *transformString = [NSString string];
- for (WXTransitionInfo *info in _propertyArray) {
- if ([info.propertyName isEqualToString:@"backgroundColor"]) {
- NSArray *array = @[
- @([info.fromValue[0] floatValue] + [info.perValue[0] floatValue] * per),
- @([info.fromValue[1] floatValue] + [info.perValue[1] floatValue] * per),
- @([info.fromValue[2] floatValue] + [info.perValue[2] floatValue] * per),
- @([info.fromValue[3] floatValue] + [info.perValue[3] floatValue] * per)];
- UIColor *color = [UIColor colorWithRed:[array[0] floatValue] green:[array[1] floatValue] blue:[array[2] floatValue] alpha:[array[3] floatValue]];
- WXPerformBlockOnMainThread(^{
- _targetComponent.view.backgroundColor = color;
- [_targetComponent.view setNeedsDisplay];
- });
- NSString *colorString = [WXConvert HexWithColor:color];
- [_oldFilterStyles setObject:colorString forKey:info.propertyName];
- }
- else if ([info.propertyName hasPrefix:@"transform"])
- {
- double currentValue = [info.fromValue doubleValue] + [info.perValue doubleValue] * per;
- NSString *newString = [NSString string];
- if ([info.propertyName isEqualToString:@"transform.rotation"]) {
- newString = [NSString stringWithFormat:@"rotate(%lfdeg)",currentValue * 180.0 / M_PI];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.rotation.x"]) {
- newString = [NSString stringWithFormat:@"rotateX(%lfdeg)",currentValue * 180.0 / M_PI];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.rotation.y"]) {
- newString = [NSString stringWithFormat:@"rotateY(%lfdeg)",currentValue * 180.0 / M_PI];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.rotation.z"]) {
- newString = [NSString stringWithFormat:@"rotateZ(%lfdeg)",currentValue * 180.0 / M_PI];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.scale.x"]) {
- newString = [NSString stringWithFormat:@"scaleX(%lf)",currentValue];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.scale.y"]) {
- newString = [NSString stringWithFormat:@"scaleY(%lf)",currentValue];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.translation.x"]) {
- newString = [NSString stringWithFormat:@"translateX(%lfpx)",currentValue / _targetComponent.weexInstance.pixelScaleFactor];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- if ([info.propertyName isEqualToString:@"transform.translation.y"]) {
- newString = [NSString stringWithFormat:@"translateY(%lfpx)",currentValue / _targetComponent.weexInstance.pixelScaleFactor];
- transformString = [transformString stringByAppendingFormat:@" %@",newString];
- }
- [_oldFilterStyles setObject:transformString forKey:@"transform"];
- }
- else
- {
- double currentValue = [info.fromValue doubleValue] + [info.perValue doubleValue] * per;
- [_oldFilterStyles setObject:@(currentValue) forKey:info.propertyName];
- }
- }
- WXPerformBlockOnMainThread(^{
- [_targetComponent _updateViewStyles:_oldFilterStyles];
- });
- [_targetComponent _updateCSSNodeStyles:_oldFilterStyles];
- [_targetComponent.weexInstance.componentManager startComponentTasks];
-}
-
-#pragma mark CADisplayLink
-- (void)_startTransitionDisplayLink
-{
- WXAssertComponentThread();
- if (!_transitionDisplayLink) {
- _transitionDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_handleTransitionDisplayLink)];
- [_transitionDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
- }
- else{
- [self _awakeTransitionDisplayLink];
- }
-}
-
-- (void)_stopTransitionDisplayLink
-{
- WXAssertComponentThread();
- if (_transitionDisplayLink) {
- [_transitionDisplayLink invalidate];
- _transitionDisplayLink = nil;
- }
-}
-
-- (BOOL)_isTransitionRunning
-{
- WXAssertComponentThread();
- BOOL yesOrNo = NO;
- if (!_transitionDisplayLink.paused && _transitionCount >= 5) {
- yesOrNo = YES;
- }
- return yesOrNo;
-}
-
-- (void)_suspendTransitionDisplayLink
-{
- WXAssertComponentThread();
- if(_transitionDisplayLink && !_transitionDisplayLink.paused){
- _transitionDisplayLink.paused = YES;
- }
-}
-
-- (void)_awakeTransitionDisplayLink
-{
- WXAssertComponentThread();
- if (_transitionDisplayLink && _transitionDisplayLink.paused) {
- _transitionDisplayLink.paused = NO;
- }
-}
-
-- (void)_handleTransitionDisplayLink
-{
- WXAssertComponentThread();
- int count = _transitionDuration * 60 / 1000;
- if (_transitionCount >= count) {
- [self _suspendTransitionDisplayLink];
- [self _resetProcessAnimationParameter];
- return;
- }
- else
- {
- [self _calculatetransitionProcessingStyle];
- }
- _transitionCount ++;
-}
-
-- (void)_resetProcessAnimationParameter
-{
- _transitionCount = 0;
- _transitionDuration = 0;
- _propertyArray = nil;
- _oldFilterStyles = nil;
- _filterStyles= nil;
-}
-
-- (NSMutableDictionary *)_filterStyles
-{
- return self.filterStyles;
-}
-
-- (NSMutableDictionary *)_oldFilterStyles
-{
- return self.oldFilterStyles;
-}
-
-#pragma mark UnitBezierp
-- (void)unitBezierp1x:(double)p1x p1y:(double)p1y p2x:(double)p2x p2y:(double)p2y
-{
- cx = 3.0 * p1x;
- bx = 3.0 * (p2x - p1x) - cx;
- ax = 1.0 - cx -bx;
-
- cy = 3.0 * p1y;
- by = 3.0 * (p2y - p1y) - cy;
- ay = 1.0 - cy - by;
-}
-
-- (double)sampleCurveX:(double)t
-{
- return ((ax * t + bx) * t + cx) * t;
-}
-
-- (double)sampleCurveY:(double)t
-{
- return ((ay * t + by) * t + cy) * t;
-}
-
-- (double)sampleCurveDerivativeX:(double)t
-{
- return (3.0 * ax * t + 2.0 * bx) * t + cx;
-}
-
-- (double)solveCurveX:(double)x epsilon:(double)epsilon
-{
- double t0;
- double t1;
- double t2;
- double x2;
- double d2;
- int i;
-
- for (t2 = x, i = 0; i < 8; i++) {
- x2 = [self sampleCurveX:t2] - x;
- if (fabs (x2) < epsilon)
- return t2;
- d2 = [self sampleCurveDerivativeX:t2];
- if (fabs(d2) < 1e-6)
- break;
- t2 = t2 - x2 / d2;
- }
- t0 = 0.0;
- t1 = 1.0;
- t2 = x;
-
- if (t2 < t0)
- return t0;
- if (t2 > t1)
- return t1;
-
- while (t0 < t1) {
- x2 = [self sampleCurveX:t2];
- if (fabs(x2 - x) < epsilon)
- return t2;
- if (x > x2)
- t0 = t2;
- else
- t1 = t2;
- t2 = (t1 - t0) * .5 + t0;
- }
- return t2;
-}
-
-- (double)solveWithx:(double)x epsilon:(double)epsilon
-{
- return [self sampleCurveY:([self solveCurveX:x epsilon:epsilon])];
-}
-@end
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Module/WXTransition.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.mm b/ios/sdk/WeexSDK/Sources/Module/WXTransition.mm
new file mode 100644
index 0000000..8e982ac
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXTransition.mm
@@ -0,0 +1,519 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#define SOLVE_EPS(dur) (1. / (1000. * (dur)))
+
+#import <QuartzCore/CATransaction.h>
+#import <QuartzCore/CADisplayLink.h>
+#import "WXComponentManager.h"
+#import "WXSDKInstance.h"
+#import "WXComponent+Layout.h"
+#import "WXComponent_internal.h"
+#import "WXTransition.h"
+#import "WXUtility.h"
+#import "WXAssert.h"
+#import "WXSDKInstance_private.h"
+#import "WXLength.h"
+
+@implementation WXTransitionInfo
+@end
+
+@interface WXTransition()
+{
+ WXComponent *_targetComponent;
+ double ax;
+ double bx;
+ double cx;
+
+ double ay;
+ double by;
+ double cy;
+
+ float _transitionDuration;
+ float _transitionDelay;
+ NSUInteger _transitionCount;
+
+ CAMediaTimingFunction *_transitionTimingFunction;
+ CADisplayLink *_transitionDisplayLink;
+
+ NSMutableDictionary *_filterStyles;
+ NSMutableDictionary *_oldFilterStyles;
+}
+
+@end
+
+@implementation WXTransition
+
+- (instancetype)initWithStyles:(NSDictionary *)styles
+{
+ if (self = [super init]) {
+ NSString *property = styles[kWXTransitionProperty];
+ NSArray *properties = [property componentsSeparatedByString:@","];
+ for (NSString *string in properties) {
+ _transitionOptions |= [self transitionOptionsFromString:string];
+ }
+ }
+ return self;
+}
+
+#pragma mark - HandleStyle
+- (WXTransitionOptions)transitionOptionsFromString:(NSString *)string
+{
+ NSDictionary<NSString*,NSNumber*> *options = @{
+ @"width": @(WXTransitionOptionsWidth),
+ @"height": @(WXTransitionOptionsHeight),
+ @"right": @(WXTransitionOptionsRight),
+ @"left": @(WXTransitionOptionsLeft),
+ @"bottom": @(WXTransitionOptionsBottom),
+ @"top": @(WXTransitionOptionsTop),
+ @"backgroundColor": @(WXTransitionOptionsBackgroundColor),
+ @"transform": @(WXTransitionOptionsTransform),
+ @"opacity": @(WXTransitionOptionsOpacity),
+ };
+ return options[string].integerValue;
+}
+
+- (void)_handleTransitionWithStyles:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles target:(WXComponent *)targetComponent
+{
+ BOOL isRunning = [self _isTransitionRunning];
+ if (isRunning) {
+ [self _rollBackTransitionWithStyles:styles];
+ }
+ else
+ {
+ [self _suspendTransitionDisplayLink];
+ }
+
+ _filterStyles = _filterStyles ?:[NSMutableDictionary new];
+ _oldFilterStyles = _oldFilterStyles ?: [NSMutableDictionary new];
+ NSMutableDictionary *futileStyles = [NSMutableDictionary new];
+
+ for (NSString *key in styles) {
+ if (self.transitionOptions & [self transitionOptionsFromString:key]) {
+ [_filterStyles setObject:styles[key] forKey:key];
+ if (![key isEqualToString:@"transform"]) {
+ if (!isRunning) {
+ [_oldFilterStyles setObject:targetComponent.styles[key] forKey:key];
+ }
+ }
+ }
+ else
+ {
+ [futileStyles setObject:styles[key] forKey:key];
+ }
+ }
+ [self updateFutileStyles:futileStyles resetStyles:nil target:targetComponent];
+
+ _targetComponent = targetComponent;
+ NSMutableDictionary *componentStyles = [NSMutableDictionary dictionaryWithDictionary:styles];
+ [componentStyles addEntriesFromDictionary:targetComponent.styles];
+
+ _transitionDuration = componentStyles[kWXTransitionDuration] ? [WXConvert CGFloat:componentStyles[kWXTransitionDuration]] : 0;
+ _transitionDelay = componentStyles[kWXTransitionDelay] ? [WXConvert CGFloat:componentStyles[kWXTransitionDelay]] : 0;
+ _transitionTimingFunction = [WXConvert CAMediaTimingFunction:componentStyles[kWXTransitionTimingFunction]];
+
+ if (_transitionDuration == 0 ) {
+ [self updateFutileStyles:_filterStyles resetStyles:nil target:targetComponent];
+ return;
+ }
+
+ if (![[NSString stringWithFormat:@"%@",_transitionTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) {
+ float vec[4] = {0.};
+ [_transitionTimingFunction getControlPointAtIndex:1 values:&vec[0]];
+ [_transitionTimingFunction getControlPointAtIndex:2 values:&vec[2]];
+ [self unitBezierp1x:vec[0] p1y:vec[1] p2x:vec[2] p2y:vec[3]];
+ }
+
+ [self _resloveTransitionProperty];
+ [self performSelector:@selector(_startTransitionDisplayLink) withObject:self afterDelay:_transitionDelay/1000];
+}
+
+- (void)updateFutileStyles:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles target:(WXComponent *)targetComponent
+{
+ [targetComponent _updateCSSNodeStyles:styles];
+ [targetComponent _resetCSSNodeStyles:resetStyles];
+ WXPerformBlockOnMainThread(^{
+ [targetComponent _updateViewStyles:styles];
+ });
+}
+
+- (void)_rollBackTransitionWithStyles:(NSDictionary *)styles
+{
+ _transitionDuration = _transitionCount * 1000 / 60;
+ _transitionCount = 0;
+ _propertyArray = nil;
+}
+
+- (void)_resloveTransitionProperty
+{
+ if (_filterStyles.count == 0) {
+ return;
+ }
+ for (NSString * name in _filterStyles.allKeys) {
+ [self _dealTransitionWithProperty:name];
+ }
+}
+
+- (void)_dealTransitionWithProperty:(NSString *)singleProperty
+{
+ if (_filterStyles[singleProperty])
+ {
+ if (!_propertyArray) {
+ _propertyArray = [NSMutableArray new];
+ }
+ if ([singleProperty isEqualToString:@"backgroundColor"]) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.fromValue = [self _dealWithColor:[WXConvert UIColor:_oldFilterStyles[singleProperty]]];
+ info.toValue = [self _dealWithColor:[WXConvert UIColor:_filterStyles[singleProperty]]];
+ info.perValue = [self _calculatePerColorRGB1:info.toValue RGB2:info.fromValue];
+ info.propertyName = singleProperty;
+ [_propertyArray addObject:info];
+ }
+ else if ([singleProperty isEqualToString:@"transform"]) {
+ NSString *transformOrigin = _filterStyles[@"transformOrigin"];
+ WXTransform *wxTransform = [[WXTransform alloc] initWithCSSValue:_filterStyles[singleProperty] origin:transformOrigin instance:_targetComponent.weexInstance];
+ WXTransform *oldTransform = _targetComponent->_transform;
+ if (wxTransform.rotateAngle != oldTransform.rotateAngle) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.rotation";
+ info.fromValue = @(oldTransform.rotateAngle);
+ info.toValue = [NSNumber numberWithDouble:wxTransform.rotateAngle];
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.rotateX != oldTransform.rotateX)
+ {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.rotation.x";
+ info.fromValue = @(oldTransform.rotateX);
+ info.toValue = [NSNumber numberWithDouble:wxTransform.rotateX];
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.rotateY != oldTransform.rotateY)
+ {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.rotation.y";
+ info.fromValue = @(oldTransform.rotateY);
+ info.toValue = [NSNumber numberWithDouble:wxTransform.rotateY];
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.rotateZ != oldTransform.rotateZ)
+ {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.rotation.z";
+ info.fromValue = @(oldTransform.rotateZ);
+ info.toValue = [NSNumber numberWithDouble:wxTransform.rotateZ];
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.scaleX != oldTransform.scaleX) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.scale.x";
+ info.fromValue = @(oldTransform.scaleX);
+ info.toValue = @(wxTransform.scaleX);
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.scaleY != oldTransform.scaleY) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.scale.y";
+ info.fromValue = @(oldTransform.scaleY);
+ info.toValue = @(wxTransform.scaleY);
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.translateX && [wxTransform.translateX floatValue] !=[oldTransform.translateX floatValue]) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.translation.x";
+ info.fromValue = @([oldTransform.translateX floatValue]);
+ info.toValue = @([wxTransform.translateX floatValue]);
+ info.perValue = @([wxTransform.translateX floatValue] - [oldTransform.translateX floatValue]);
+ [_propertyArray addObject:info];
+ }
+ if (wxTransform.translateY && [wxTransform.translateY floatValue] !=[oldTransform.translateY floatValue]) {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.propertyName = @"transform.translation.y";
+ info.fromValue = @([oldTransform.translateY floatValue]);
+ info.toValue = @([wxTransform.translateY floatValue]);
+ info.perValue = @([wxTransform.translateY floatValue] - [oldTransform.translateY floatValue]);
+ [_propertyArray addObject:info];
+ }
+ _targetComponent->_transform = wxTransform;
+ }
+ else
+ {
+ WXTransitionInfo *info = [WXTransitionInfo new];
+ info.fromValue = @(_oldFilterStyles[singleProperty] ? [WXConvert CGFloat:_oldFilterStyles[singleProperty]] : 0);
+ info.toValue = @(_filterStyles[singleProperty] ? [WXConvert CGFloat:_filterStyles[singleProperty]] : 0 );
+ info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]);
+ info.propertyName = singleProperty;
+ [_propertyArray addObject:info];
+ }
+ }
+}
+
+- (NSArray *)_dealWithColor:(UIColor *)color
+{
+ CGFloat R, G, B, A;
+ [color getRed:&R green:&G blue:&B alpha:&A];
+ return @[@(R),@(G),@(B),@(A)];
+}
+
+- (NSArray *)_calculatePerColorRGB1:(NSArray *)RGB1 RGB2:(NSArray *)RGB2
+{
+ CGFloat R = [RGB1[0] doubleValue] - [RGB2[0] doubleValue];
+ CGFloat G = [RGB1[1] doubleValue] - [RGB2[1] doubleValue];
+ CGFloat B = [RGB1[2] doubleValue] - [RGB2[2] doubleValue];
+ CGFloat A = [RGB1[3] doubleValue] - [RGB2[3] doubleValue];
+ return @[@(R),@(G),@(B),@(A)];
+}
+
+- (void)_calculatetransitionProcessingStyle
+{
+ if (_propertyArray.count == 0) {
+ return;
+ }
+ double per = 1000 * (_transitionCount + 1 ) / (60 * _transitionDuration);//linear
+ if (![[NSString stringWithFormat:@"%@",_transitionTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) {
+ per = [self solveWithx:((_transitionCount+2)*16)/_transitionDuration epsilon:SOLVE_EPS(_transitionDuration)];
+ }
+ NSString *transformString = [NSString string];
+ for (WXTransitionInfo *info in _propertyArray) {
+ if ([info.propertyName isEqualToString:@"backgroundColor"]) {
+ NSArray *array = @[
+ @([info.fromValue[0] floatValue] + [info.perValue[0] floatValue] * per),
+ @([info.fromValue[1] floatValue] + [info.perValue[1] floatValue] * per),
+ @([info.fromValue[2] floatValue] + [info.perValue[2] floatValue] * per),
+ @([info.fromValue[3] floatValue] + [info.perValue[3] floatValue] * per)];
+ UIColor *color = [UIColor colorWithRed:[array[0] floatValue] green:[array[1] floatValue] blue:[array[2] floatValue] alpha:[array[3] floatValue]];
+ WXPerformBlockOnMainThread(^{
+ _targetComponent.view.backgroundColor = color;
+ [_targetComponent.view setNeedsDisplay];
+ });
+ NSString *colorString = [WXConvert HexWithColor:color];
+ [_oldFilterStyles setObject:colorString forKey:info.propertyName];
+ }
+ else if ([info.propertyName hasPrefix:@"transform"])
+ {
+ double currentValue = [info.fromValue doubleValue] + [info.perValue doubleValue] * per;
+ NSString *newString = [NSString string];
+ if ([info.propertyName isEqualToString:@"transform.rotation"]) {
+ newString = [NSString stringWithFormat:@"rotate(%lfdeg)",currentValue * 180.0 / M_PI];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.rotation.x"]) {
+ newString = [NSString stringWithFormat:@"rotateX(%lfdeg)",currentValue * 180.0 / M_PI];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.rotation.y"]) {
+ newString = [NSString stringWithFormat:@"rotateY(%lfdeg)",currentValue * 180.0 / M_PI];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.rotation.z"]) {
+ newString = [NSString stringWithFormat:@"rotateZ(%lfdeg)",currentValue * 180.0 / M_PI];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.scale.x"]) {
+ newString = [NSString stringWithFormat:@"scaleX(%lf)",currentValue];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.scale.y"]) {
+ newString = [NSString stringWithFormat:@"scaleY(%lf)",currentValue];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.translation.x"]) {
+ newString = [NSString stringWithFormat:@"translateX(%lfpx)",currentValue / _targetComponent.weexInstance.pixelScaleFactor];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ if ([info.propertyName isEqualToString:@"transform.translation.y"]) {
+ newString = [NSString stringWithFormat:@"translateY(%lfpx)",currentValue / _targetComponent.weexInstance.pixelScaleFactor];
+ transformString = [transformString stringByAppendingFormat:@" %@",newString];
+ }
+ [_oldFilterStyles setObject:transformString forKey:@"transform"];
+ }
+ else
+ {
+ double currentValue = [info.fromValue doubleValue] + [info.perValue doubleValue] * per;
+ [_oldFilterStyles setObject:@(currentValue) forKey:info.propertyName];
+ }
+ }
+ WXPerformBlockOnMainThread(^{
+ [_targetComponent _updateViewStyles:_oldFilterStyles];
+ });
+ [_targetComponent _updateCSSNodeStyles:_oldFilterStyles];
+ [_targetComponent.weexInstance.componentManager startComponentTasks];
+}
+
+#pragma mark CADisplayLink
+- (void)_startTransitionDisplayLink
+{
+ WXAssertComponentThread();
+ if (!_transitionDisplayLink) {
+ _transitionDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_handleTransitionDisplayLink)];
+ [_transitionDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+ }
+ else{
+ [self _awakeTransitionDisplayLink];
+ }
+}
+
+- (void)_stopTransitionDisplayLink
+{
+ WXAssertComponentThread();
+ if (_transitionDisplayLink) {
+ [_transitionDisplayLink invalidate];
+ _transitionDisplayLink = nil;
+ }
+}
+
+- (BOOL)_isTransitionRunning
+{
+ WXAssertComponentThread();
+ BOOL yesOrNo = NO;
+ if (!_transitionDisplayLink.paused && _transitionCount >= 5) {
+ yesOrNo = YES;
+ }
+ return yesOrNo;
+}
+
+- (void)_suspendTransitionDisplayLink
+{
+ WXAssertComponentThread();
+ if(_transitionDisplayLink && !_transitionDisplayLink.paused){
+ _transitionDisplayLink.paused = YES;
+ }
+}
+
+- (void)_awakeTransitionDisplayLink
+{
+ WXAssertComponentThread();
+ if (_transitionDisplayLink && _transitionDisplayLink.paused) {
+ _transitionDisplayLink.paused = NO;
+ }
+}
+
+- (void)_handleTransitionDisplayLink
+{
+ WXAssertComponentThread();
+ int count = _transitionDuration * 60 / 1000;
+ if (_transitionCount >= count) {
+ [self _suspendTransitionDisplayLink];
+ [self _resetProcessAnimationParameter];
+ return;
+ }
+ else
+ {
+ [self _calculatetransitionProcessingStyle];
+ }
+ _transitionCount ++;
+}
+
+- (void)_resetProcessAnimationParameter
+{
+ _transitionCount = 0;
+ _transitionDuration = 0;
+ _propertyArray = nil;
+ _oldFilterStyles = nil;
+ _filterStyles= nil;
+}
+
+- (NSMutableDictionary *)_filterStyles
+{
+ return self.filterStyles;
+}
+
+- (NSMutableDictionary *)_oldFilterStyles
+{
+ return self.oldFilterStyles;
+}
+
+#pragma mark UnitBezierp
+- (void)unitBezierp1x:(double)p1x p1y:(double)p1y p2x:(double)p2x p2y:(double)p2y
+{
+ cx = 3.0 * p1x;
+ bx = 3.0 * (p2x - p1x) - cx;
+ ax = 1.0 - cx -bx;
+
+ cy = 3.0 * p1y;
+ by = 3.0 * (p2y - p1y) - cy;
+ ay = 1.0 - cy - by;
+}
+
+- (double)sampleCurveX:(double)t
+{
+ return ((ax * t + bx) * t + cx) * t;
+}
+
+- (double)sampleCurveY:(double)t
+{
+ return ((ay * t + by) * t + cy) * t;
+}
+
+- (double)sampleCurveDerivativeX:(double)t
+{
+ return (3.0 * ax * t + 2.0 * bx) * t + cx;
+}
+
+- (double)solveCurveX:(double)x epsilon:(double)epsilon
+{
+ double t0;
+ double t1;
+ double t2;
+ double x2;
+ double d2;
+ int i;
+
+ for (t2 = x, i = 0; i < 8; i++) {
+ x2 = [self sampleCurveX:t2] - x;
+ if (fabs (x2) < epsilon)
+ return t2;
+ d2 = [self sampleCurveDerivativeX:t2];
+ if (fabs(d2) < 1e-6)
+ break;
+ t2 = t2 - x2 / d2;
+ }
+ t0 = 0.0;
+ t1 = 1.0;
+ t2 = x;
+
+ if (t2 < t0)
+ return t0;
+ if (t2 > t1)
+ return t1;
+
+ while (t0 < t1) {
+ x2 = [self sampleCurveX:t2];
+ if (fabs(x2 - x) < epsilon)
+ return t2;
+ if (x > x2)
+ t0 = t2;
+ else
+ t1 = t2;
+ t2 = (t1 - t0) * .5 + t0;
+ }
+ return t2;
+}
+
+- (double)solveWithx:(double)x epsilon:(double)epsilon
+{
+ return [self sampleCurveY:([self solveCurveX:x epsilon:epsilon])];
+}
+@end
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
index 2744e60..a303ddb 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
@@ -63,6 +63,9 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
{
if ([value isKindOfClass:[NSString class]]) {
NSString *valueString = (NSString *)value;
+ if (valueString.length <=0) {
+ return NAN;
+ }
if ([valueString hasSuffix:@"px"] || [valueString hasSuffix:@"wx"]) {
valueString = [valueString substringToIndex:(valueString.length - 2)];
}
@@ -72,12 +75,32 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
value = [value substringWithRange:NSMakeRange(start, end-start)];
return [self safeAreaInset:value];
}
+ //value maybe not number ,such as 100%
+ if (![WXConvert checkStringIsRealNum:valueString]) {
+ return NAN;
+ }
return [valueString doubleValue];
}
return [self double:value];
}
++ (BOOL)checkStringIsRealNum:(NSString *)checkedNumString {
+ NSScanner* scan = [NSScanner scannerWithString:checkedNumString];
+ int intVal;
+ BOOL isInt = [scan scanInt:&intVal] && [scan isAtEnd];
+ if (isInt) {
+ return YES;
+ }
+ float floatVal;
+ BOOL isFloat = [scan scanFloat:&floatVal] && [scan isAtEnd];
+ if (isFloat) {
+ return YES;
+ }
+
+ return NO;
+}
+
+ (CGFloat)safeAreaInset:(NSString*)value
{
static NSArray * directionArray = nil;
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 0e2bb06..b1b852a 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -253,6 +253,9 @@ _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
*/
+ (CGFloat)defaultPixelScaleFactor;
+#if defined __cplusplus
+extern "C" {
+#endif
/**
* @abstract Returns the scale of the main screen.
*
@@ -276,7 +279,11 @@ CGFloat WXFloorPixelValue(CGFloat value);
*
*/
CGFloat WXCeilPixelValue(CGFloat value);
-
+
+#if defined __cplusplus
+};
+#endif
+
/**
* @abstract check whether the file is exist
*
@@ -404,6 +411,10 @@ CGPoint WXPixelPointResize(CGPoint value) DEPRECATED_MSG_ATTRIBUTE("Use WXPixelS
*/
+ (NSDictionary *_Nullable)linearGradientWithBackgroundImage:(NSString *_Nullable)backgroundImage;
+#if defined __cplusplus
+extern "C" {
+#endif
+
/**
* @abstract compare float a and b, if a equal b, return true,or reture false.
*
@@ -435,6 +446,10 @@ BOOL WXFloatGreaterThan(CGFloat a, CGFloat b);
*/
BOOL WXFloatGreaterThanWithPrecision(CGFloat a,CGFloat b,double precision);
+#if defined __cplusplus
+};
+#endif
+
/**
* @abstract convert returnKeyType to type string .
*