Background performance optimizations

This commit is contained in:
Rossen Hristov
2016-06-24 14:49:11 +03:00
parent 99c0142aa4
commit 53a699b50b
2 changed files with 92 additions and 49 deletions

View File

@ -10,8 +10,6 @@
clipPath: string, clipPath: string,
backgroundColor: number, backgroundColor: number,
backgroundImage: android.graphics.Bitmap, backgroundImage: android.graphics.Bitmap,
backgroundImageWidth: number,
backgroundImageHeight: number,
backgroundRepeat: string, backgroundRepeat: string,
backgroundPosition: string, backgroundPosition: string,
backgroundPositionParsedCSSValues: native.Array<CSSValue>, backgroundPositionParsedCSSValues: native.Array<CSSValue>,
@ -24,8 +22,6 @@
public getClipPath(): string; public getClipPath(): string;
public getBackgroundColor(): number; public getBackgroundColor(): number;
public getBackgroundImage(): android.graphics.Bitmap; public getBackgroundImage(): android.graphics.Bitmap;
public getBackgroundImageWidth(): number;
public getBackgroundImageHeight(): number;
public getBackgroundRepeat(): string; public getBackgroundRepeat(): string;
public getBackgroundPosition(): string; public getBackgroundPosition(): string;
public getBackgroundSize(): string; public getBackgroundSize(): string;

View File

@ -8,8 +8,8 @@ import { CacheLayerType } from "utils/utils";
import cssValue = require("css-value"); import cssValue = require("css-value");
import background = require("ui/styling/background"); import background = require("ui/styling/background");
var button: typeof buttonModule; let button: typeof buttonModule;
var style: typeof styleModule; let style: typeof styleModule;
function ensureLazyRequires() { function ensureLazyRequires() {
if (!button) { if (!button) {
@ -25,7 +25,7 @@ global.moduleMerge(common, exports);
// We are using "ad" here to avoid namespace collision with the global android object // We are using "ad" here to avoid namespace collision with the global android object
export module ad { export module ad {
var SDK: number; let SDK: number;
function getSDK() { function getSDK() {
if (!SDK) { if (!SDK) {
SDK = android.os.Build.VERSION.SDK_INT; SDK = android.os.Build.VERSION.SDK_INT;
@ -34,62 +34,46 @@ export module ad {
return SDK; return SDK;
} }
var _defaultBackgrounds = new Map<string, android.graphics.drawable.Drawable>(); let _defaultBackgrounds = new Map<string, android.graphics.drawable.Drawable>();
export function onBackgroundOrBorderPropertyChanged(v: view.View) { export function onBackgroundOrBorderPropertyChanged(v: view.View) {
var nativeView = <android.view.View>v._nativeView; let nativeView = <android.view.View>v._nativeView;
var cache = <CacheLayerType>v._nativeView;
if (!nativeView) { if (!nativeView) {
return; return;
} }
ensureLazyRequires(); ensureLazyRequires();
var clipPathValue = v.style._getValue(style.clipPathProperty); let clipPath = v.style._getValue(style.clipPathProperty);
let background = <background.Background>v.style._getValue(style.backgroundInternalProperty);
var backgroundValue = <background.Background>v.style._getValue(style.backgroundInternalProperty); let borderWidth = v.borderWidth;
var borderWidth = v.borderWidth; let backgroundDrawable = nativeView.getBackground();
var bkg = nativeView.getBackground(); let density = utils.layout.getDisplayDensity();
let cache = <CacheLayerType>v._nativeView;
var density = utils.layout.getDisplayDensity(); if (v instanceof button.Button && !types.isNullOrUndefined(backgroundDrawable) && types.isFunction(backgroundDrawable.setColorFilter) &&
v.borderWidth === 0 && v.borderRadius === 0 && !clipPath &&
if (v instanceof button.Button && !types.isNullOrUndefined(bkg) && types.isFunction(bkg.setColorFilter) &&
v.borderWidth === 0 && v.borderRadius === 0 && !clipPathValue &&
types.isNullOrUndefined(v.style._getValue(style.backgroundImageProperty)) && types.isNullOrUndefined(v.style._getValue(style.backgroundImageProperty)) &&
!types.isNullOrUndefined(v.style._getValue(style.backgroundColorProperty))) { !types.isNullOrUndefined(v.style._getValue(style.backgroundColorProperty))) {
let backgroundColor = (<any>bkg).backgroundColor = v.style._getValue(style.backgroundColorProperty).android; let backgroundColor = (<any>backgroundDrawable).backgroundColor = v.style._getValue(style.backgroundColorProperty).android;
bkg.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN); backgroundDrawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN);
(<any>bkg).backgroundColor = backgroundColor; (<any>backgroundDrawable).backgroundColor = backgroundColor;
} }
else if (v.borderWidth || v.borderRadius || clipPathValue || !backgroundValue.isEmpty()) { else if (v.borderWidth || v.borderRadius || clipPath || !background.isEmpty()) {
if (!(bkg instanceof org.nativescript.widgets.BorderDrawable)) { if (!(backgroundDrawable instanceof org.nativescript.widgets.BorderDrawable)) {
bkg = new org.nativescript.widgets.BorderDrawable(density);
let viewClass = types.getClass(v); let viewClass = types.getClass(v);
if (!(v instanceof button.Button) && !_defaultBackgrounds.has(viewClass)) { if (!(v instanceof button.Button) && !_defaultBackgrounds.has(viewClass)) {
_defaultBackgrounds.set(viewClass, nativeView.getBackground()); _defaultBackgrounds.set(viewClass, nativeView.getBackground());
} }
nativeView.setBackground(bkg); backgroundDrawable = new org.nativescript.widgets.BorderDrawable(density);
refreshBorderDrawable(v, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
nativeView.setBackground(backgroundDrawable);
}
else {
refreshBorderDrawable(v, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
} }
(<org.nativescript.widgets.BorderDrawable>bkg).refresh( if ((v.borderWidth || v.borderRadius || clipPath) && getSDK() < 18) {
v.borderWidth,
v.borderColor ? v.borderColor.android : 0,
v.borderRadius,
clipPathValue,
(backgroundValue.color && backgroundValue.color.android) ? backgroundValue.color.android : 0,
(backgroundValue.image && backgroundValue.image.android) ? backgroundValue.image.android : null,
(backgroundValue.image && backgroundValue.image.android) ? backgroundValue.image.width : 0,
(backgroundValue.image && backgroundValue.image.android) ? backgroundValue.image.height : 0,
backgroundValue.repeat,
backgroundValue.position,
backgroundValue.position ? createNativeCSSValueArray(backgroundValue.position) : null,
backgroundValue.size,
backgroundValue.size ? createNativeCSSValueArray(backgroundValue.size) : null
);
if ((v.borderWidth || v.borderRadius || clipPathValue) && getSDK() < 18) {
// Switch to software because of unsupported canvas methods if hardware acceleration is on: // Switch to software because of unsupported canvas methods if hardware acceleration is on:
// http://developer.android.com/guide/topics/graphics/hardware-accel.html // http://developer.android.com/guide/topics/graphics/hardware-accel.html
cache.layerType = cache.getLayerType(); cache.layerType = cache.getLayerType();
@ -99,7 +83,7 @@ export module ad {
else { else {
// reset the value with the default native value // reset the value with the default native value
if (v instanceof button.Button) { if (v instanceof button.Button) {
var nativeButton = new android.widget.Button(nativeView.getContext()); let nativeButton = new android.widget.Button(nativeView.getContext());
nativeView.setBackground(nativeButton.getBackground()); nativeView.setBackground(nativeButton.getBackground());
} }
else { else {
@ -124,7 +108,70 @@ export module ad {
} }
} }
function createNativeCSSValueArray(css: string): any{ function refreshBorderDrawable(view: view.View, borderDrawable: org.nativescript.widgets.BorderDrawable){
let background = <background.Background>view.style._getValue(style.backgroundInternalProperty);
let borderWidth: number = view.borderWidth;
let borderColor: number = 0;
if (view.borderColor && view.borderColor.android){
borderColor = view.borderColor.android;
}
let borderRadius: number = view.borderRadius;
let clipPath: string = view.style._getValue(style.clipPathProperty);
let backgroundColor: number = 0;
let backgroundImage: android.graphics.Bitmap = null;
let backgroundRepeat: string = null;
let backgroundPosition: string = null;
let backgroundPositionParsedCSSValues: native.Array<org.nativescript.widgets.CSSValue> = null;
let backgroundSize: string = null;
let backgroundSizeParsedCSSValues: native.Array<org.nativescript.widgets.CSSValue> = null;
if (background){
if (background.color && background.color.android){
backgroundColor = background.color.android;
}
if (background.image && background.image.android){
backgroundImage = background.image.android;
}
if (background.position){
backgroundPosition = background.position;
backgroundPositionParsedCSSValues = createNativeCSSValueArray(background.position);
}
if (background.size){
backgroundSize = background.size;
backgroundSizeParsedCSSValues = createNativeCSSValueArray(background.size);
}
}
let newBackground = JSON.stringify({
w: borderWidth,
c: borderColor,
r: borderRadius,
cp: clipPath,
bc: backgroundColor,
bi: backgroundImage ? backgroundImage.hashCode() : "",
br: backgroundRepeat,
bp: backgroundPosition,
bs: backgroundSize
});
if (newBackground !== view["android-backround"]){
borderDrawable.refresh(
borderWidth,
borderColor,
borderRadius,
clipPath,
backgroundColor,
backgroundImage,
backgroundRepeat,
backgroundPosition,
backgroundPositionParsedCSSValues,
backgroundSize,
backgroundSizeParsedCSSValues
);
view["android-backround"] = newBackground;
}
}
function createNativeCSSValueArray(css: string): native.Array<org.nativescript.widgets.CSSValue>{
if (!css){ if (!css){
return null; return null;
} }