chore: format

This commit is contained in:
Nathan Walker
2020-07-05 14:57:06 -07:00
parent 8f2900ad0b
commit da3c0b973d
379 changed files with 71587 additions and 54582 deletions

View File

@@ -6,291 +6,335 @@ import { LinearGradient } from "./linear-gradient";
import { Color } from "../../color";
export class Background implements BackgroundDefinition {
public static default = new Background();
public static default = new Background();
public color: Color;
public image: string | LinearGradient;
public repeat: BackgroundRepeat;
public position: string;
public size: string;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderTopWidth: number = 0;
public borderRightWidth: number = 0;
public borderBottomWidth: number = 0;
public borderLeftWidth: number = 0;
public borderTopLeftRadius: number = 0;
public borderTopRightRadius: number = 0;
public borderBottomLeftRadius: number = 0;
public borderBottomRightRadius: number = 0;
public clipPath: string;
public color: Color;
public image: string | LinearGradient;
public repeat: BackgroundRepeat;
public position: string;
public size: string;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderTopWidth: number = 0;
public borderRightWidth: number = 0;
public borderBottomWidth: number = 0;
public borderLeftWidth: number = 0;
public borderTopLeftRadius: number = 0;
public borderTopRightRadius: number = 0;
public borderBottomLeftRadius: number = 0;
public borderBottomRightRadius: number = 0;
public clipPath: string;
private clone(): Background {
const clone = new Background();
private clone(): Background {
const clone = new Background();
clone.color = this.color;
clone.image = this.image;
clone.repeat = this.repeat;
clone.position = this.position;
clone.size = this.size;
clone.borderTopColor = this.borderTopColor;
clone.borderRightColor = this.borderRightColor;
clone.borderBottomColor = this.borderBottomColor;
clone.borderLeftColor = this.borderLeftColor;
clone.borderTopWidth = this.borderTopWidth;
clone.borderRightWidth = this.borderRightWidth;
clone.borderBottomWidth = this.borderBottomWidth;
clone.borderLeftWidth = this.borderLeftWidth;
clone.borderTopLeftRadius = this.borderTopLeftRadius;
clone.borderTopRightRadius = this.borderTopRightRadius;
clone.borderBottomRightRadius = this.borderBottomRightRadius;
clone.borderBottomLeftRadius = this.borderBottomLeftRadius;
clone.clipPath = this.clipPath;
clone.color = this.color;
clone.image = this.image;
clone.repeat = this.repeat;
clone.position = this.position;
clone.size = this.size;
clone.borderTopColor = this.borderTopColor;
clone.borderRightColor = this.borderRightColor;
clone.borderBottomColor = this.borderBottomColor;
clone.borderLeftColor = this.borderLeftColor;
clone.borderTopWidth = this.borderTopWidth;
clone.borderRightWidth = this.borderRightWidth;
clone.borderBottomWidth = this.borderBottomWidth;
clone.borderLeftWidth = this.borderLeftWidth;
clone.borderTopLeftRadius = this.borderTopLeftRadius;
clone.borderTopRightRadius = this.borderTopRightRadius;
clone.borderBottomRightRadius = this.borderBottomRightRadius;
clone.borderBottomLeftRadius = this.borderBottomLeftRadius;
clone.clipPath = this.clipPath;
return clone;
}
return clone;
}
public withColor(value: Color): Background {
const clone = this.clone();
clone.color = value;
public withColor(value: Color): Background {
const clone = this.clone();
clone.color = value;
return clone;
}
return clone;
}
public withImage(value: string | LinearGradient): Background {
const clone = this.clone();
clone.image = value;
public withImage(value: string | LinearGradient): Background {
const clone = this.clone();
clone.image = value;
return clone;
}
return clone;
}
public withRepeat(value: BackgroundRepeat): Background {
const clone = this.clone();
clone.repeat = value;
public withRepeat(value: BackgroundRepeat): Background {
const clone = this.clone();
clone.repeat = value;
return clone;
}
return clone;
}
public withPosition(value: string): Background {
const clone = this.clone();
clone.position = value;
public withPosition(value: string): Background {
const clone = this.clone();
clone.position = value;
return clone;
}
return clone;
}
public withSize(value: string): Background {
const clone = this.clone();
clone.size = value;
public withSize(value: string): Background {
const clone = this.clone();
clone.size = value;
return clone;
}
return clone;
}
public withBorderTopColor(value: Color): Background {
const clone = this.clone();
clone.borderTopColor = value;
public withBorderTopColor(value: Color): Background {
const clone = this.clone();
clone.borderTopColor = value;
return clone;
}
return clone;
}
public withBorderRightColor(value: Color): Background {
const clone = this.clone();
clone.borderRightColor = value;
public withBorderRightColor(value: Color): Background {
const clone = this.clone();
clone.borderRightColor = value;
return clone;
}
return clone;
}
public withBorderBottomColor(value: Color): Background {
const clone = this.clone();
clone.borderBottomColor = value;
public withBorderBottomColor(value: Color): Background {
const clone = this.clone();
clone.borderBottomColor = value;
return clone;
}
return clone;
}
public withBorderLeftColor(value: Color): Background {
const clone = this.clone();
clone.borderLeftColor = value;
public withBorderLeftColor(value: Color): Background {
const clone = this.clone();
clone.borderLeftColor = value;
return clone;
}
return clone;
}
public withBorderTopWidth(value: number): Background {
const clone = this.clone();
clone.borderTopWidth = value;
public withBorderTopWidth(value: number): Background {
const clone = this.clone();
clone.borderTopWidth = value;
return clone;
}
return clone;
}
public withBorderRightWidth(value: number): Background {
const clone = this.clone();
clone.borderRightWidth = value;
public withBorderRightWidth(value: number): Background {
const clone = this.clone();
clone.borderRightWidth = value;
return clone;
}
return clone;
}
public withBorderBottomWidth(value: number): Background {
const clone = this.clone();
clone.borderBottomWidth = value;
public withBorderBottomWidth(value: number): Background {
const clone = this.clone();
clone.borderBottomWidth = value;
return clone;
}
return clone;
}
public withBorderLeftWidth(value: number): Background {
const clone = this.clone();
clone.borderLeftWidth = value;
public withBorderLeftWidth(value: number): Background {
const clone = this.clone();
clone.borderLeftWidth = value;
return clone;
}
return clone;
}
public withBorderTopLeftRadius(value: number): Background {
const clone = this.clone();
clone.borderTopLeftRadius = value;
public withBorderTopLeftRadius(value: number): Background {
const clone = this.clone();
clone.borderTopLeftRadius = value;
return clone;
}
return clone;
}
public withBorderTopRightRadius(value: number): Background {
const clone = this.clone();
clone.borderTopRightRadius = value;
public withBorderTopRightRadius(value: number): Background {
const clone = this.clone();
clone.borderTopRightRadius = value;
return clone;
}
return clone;
}
public withBorderBottomRightRadius(value: number): Background {
const clone = this.clone();
clone.borderBottomRightRadius = value;
public withBorderBottomRightRadius(value: number): Background {
const clone = this.clone();
clone.borderBottomRightRadius = value;
return clone;
}
return clone;
}
public withBorderBottomLeftRadius(value: number): Background {
const clone = this.clone();
clone.borderBottomLeftRadius = value;
public withBorderBottomLeftRadius(value: number): Background {
const clone = this.clone();
clone.borderBottomLeftRadius = value;
return clone;
}
return clone;
}
public withClipPath(value: string): Background {
const clone = this.clone();
clone.clipPath = value;
public withClipPath(value: string): Background {
const clone = this.clone();
clone.clipPath = value;
return clone;
}
return clone;
}
public isEmpty(): boolean {
return !this.color
&& !this.image
&& !this.hasBorderWidth()
&& !this.hasBorderRadius()
&& !this.clipPath;
}
public isEmpty(): boolean {
return (
!this.color &&
!this.image &&
!this.hasBorderWidth() &&
!this.hasBorderRadius() &&
!this.clipPath
);
}
public static equals(value1: Background, value2: Background): boolean {
// both values are falsy
if (!value1 && !value2) {
return true;
}
public static equals(value1: Background, value2: Background): boolean {
// both values are falsy
if (!value1 && !value2) {
return true;
}
// only one is falsy
if (!value1 || !value2) {
return false;
}
// only one is falsy
if (!value1 || !value2) {
return false;
}
let imagesEqual = false;
if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
imagesEqual = LinearGradient.equals(value1, value2);
} else {
imagesEqual = value1.image === value2.image;
}
let imagesEqual = false;
if (
value1 instanceof LinearGradient &&
value2 instanceof LinearGradient
) {
imagesEqual = LinearGradient.equals(value1, value2);
} else {
imagesEqual = value1.image === value2.image;
}
return Color.equals(value1.color, value2.color)
&& imagesEqual
&& value1.position === value2.position
&& value1.repeat === value2.repeat
&& value1.size === value2.size
&& Color.equals(value1.borderTopColor, value2.borderTopColor)
&& Color.equals(value1.borderRightColor, value2.borderRightColor)
&& Color.equals(value1.borderBottomColor, value2.borderBottomColor)
&& Color.equals(value1.borderLeftColor, value2.borderLeftColor)
&& value1.borderTopWidth === value2.borderTopWidth
&& value1.borderRightWidth === value2.borderRightWidth
&& value1.borderBottomWidth === value2.borderBottomWidth
&& value1.borderLeftWidth === value2.borderLeftWidth
&& value1.borderTopLeftRadius === value2.borderTopLeftRadius
&& value1.borderTopRightRadius === value2.borderTopRightRadius
&& value1.borderBottomRightRadius === value2.borderBottomRightRadius
&& value1.borderBottomLeftRadius === value2.borderBottomLeftRadius
&& value1.clipPath === value2.clipPath;
}
return (
Color.equals(value1.color, value2.color) &&
imagesEqual &&
value1.position === value2.position &&
value1.repeat === value2.repeat &&
value1.size === value2.size &&
Color.equals(value1.borderTopColor, value2.borderTopColor) &&
Color.equals(value1.borderRightColor, value2.borderRightColor) &&
Color.equals(value1.borderBottomColor, value2.borderBottomColor) &&
Color.equals(value1.borderLeftColor, value2.borderLeftColor) &&
value1.borderTopWidth === value2.borderTopWidth &&
value1.borderRightWidth === value2.borderRightWidth &&
value1.borderBottomWidth === value2.borderBottomWidth &&
value1.borderLeftWidth === value2.borderLeftWidth &&
value1.borderTopLeftRadius === value2.borderTopLeftRadius &&
value1.borderTopRightRadius === value2.borderTopRightRadius &&
value1.borderBottomRightRadius === value2.borderBottomRightRadius &&
value1.borderBottomLeftRadius === value2.borderBottomLeftRadius &&
value1.clipPath === value2.clipPath
);
}
public hasBorderColor(): boolean {
return !!this.borderTopColor || !!this.borderRightColor || !!this.borderBottomColor || !!this.borderLeftColor;
}
public hasBorderColor(): boolean {
return (
!!this.borderTopColor ||
!!this.borderRightColor ||
!!this.borderBottomColor ||
!!this.borderLeftColor
);
}
public hasBorderWidth(): boolean {
return this.borderTopWidth > 0
|| this.borderRightWidth > 0
|| this.borderBottomWidth > 0
|| this.borderLeftWidth > 0;
}
public hasBorderWidth(): boolean {
return (
this.borderTopWidth > 0 ||
this.borderRightWidth > 0 ||
this.borderBottomWidth > 0 ||
this.borderLeftWidth > 0
);
}
public hasBorderRadius(): boolean {
return this.borderTopLeftRadius > 0
|| this.borderTopRightRadius > 0
|| this.borderBottomRightRadius > 0
|| this.borderBottomLeftRadius > 0;
}
public hasBorderRadius(): boolean {
return (
this.borderTopLeftRadius > 0 ||
this.borderTopRightRadius > 0 ||
this.borderBottomRightRadius > 0 ||
this.borderBottomLeftRadius > 0
);
}
public hasUniformBorderColor(): boolean {
return Color.equals(this.borderTopColor, this.borderRightColor)
&& Color.equals(this.borderTopColor, this.borderBottomColor)
&& Color.equals(this.borderTopColor, this.borderLeftColor);
}
public hasUniformBorderColor(): boolean {
return (
Color.equals(this.borderTopColor, this.borderRightColor) &&
Color.equals(this.borderTopColor, this.borderBottomColor) &&
Color.equals(this.borderTopColor, this.borderLeftColor)
);
}
public hasUniformBorderWidth(): boolean {
return this.borderTopWidth === this.borderRightWidth
&& this.borderTopWidth === this.borderBottomWidth
&& this.borderTopWidth === this.borderLeftWidth;
}
public hasUniformBorderWidth(): boolean {
return (
this.borderTopWidth === this.borderRightWidth &&
this.borderTopWidth === this.borderBottomWidth &&
this.borderTopWidth === this.borderLeftWidth
);
}
public hasUniformBorderRadius(): boolean {
return this.borderTopLeftRadius === this.borderTopRightRadius
&& this.borderTopLeftRadius === this.borderBottomRightRadius
&& this.borderTopLeftRadius === this.borderBottomLeftRadius;
}
public hasUniformBorderRadius(): boolean {
return (
this.borderTopLeftRadius === this.borderTopRightRadius &&
this.borderTopLeftRadius === this.borderBottomRightRadius &&
this.borderTopLeftRadius === this.borderBottomLeftRadius
);
}
public hasUniformBorder(): boolean {
return this.hasUniformBorderColor()
&& this.hasUniformBorderWidth()
&& this.hasUniformBorderRadius();
}
public hasUniformBorder(): boolean {
return (
this.hasUniformBorderColor() &&
this.hasUniformBorderWidth() &&
this.hasUniformBorderRadius()
);
}
public getUniformBorderColor(): Color {
if (this.hasUniformBorderColor()) {
return this.borderTopColor;
}
public getUniformBorderColor(): Color {
if (this.hasUniformBorderColor()) {
return this.borderTopColor;
}
return undefined;
}
return undefined;
}
public getUniformBorderWidth(): number {
if (this.hasUniformBorderWidth()) {
return this.borderTopWidth;
}
public getUniformBorderWidth(): number {
if (this.hasUniformBorderWidth()) {
return this.borderTopWidth;
}
return 0;
}
return 0;
}
public getUniformBorderRadius(): number {
if (this.hasUniformBorderRadius()) {
return this.borderTopLeftRadius;
}
public getUniformBorderRadius(): number {
if (this.hasUniformBorderRadius()) {
return this.borderTopLeftRadius;
}
return 0;
}
return 0;
}
public toString(): string {
return `isEmpty: ${this.isEmpty()}; color: ${this.color}; image: ${this.image}; repeat: ${this.repeat}; position: ${this.position}; size: ${this.size}; borderTopColor: ${this.borderTopColor}; borderRightColor: ${this.borderRightColor}; borderBottomColor: ${this.borderBottomColor}; borderLeftColor: ${this.borderLeftColor}; borderTopWidth: ${this.borderTopWidth}; borderRightWidth: ${this.borderRightWidth}; borderBottomWidth: ${this.borderBottomWidth}; borderLeftWidth: ${this.borderLeftWidth}; borderTopLeftRadius: ${this.borderTopLeftRadius}; borderTopRightRadius: ${this.borderTopRightRadius}; borderBottomRightRadius: ${this.borderBottomRightRadius}; borderBottomLeftRadius: ${this.borderBottomLeftRadius}; clipPath: ${this.clipPath};`;
}
public toString(): string {
return `isEmpty: ${this.isEmpty()}; color: ${this.color}; image: ${
this.image
}; repeat: ${this.repeat}; position: ${this.position}; size: ${
this.size
}; borderTopColor: ${this.borderTopColor}; borderRightColor: ${
this.borderRightColor
}; borderBottomColor: ${this.borderBottomColor}; borderLeftColor: ${
this.borderLeftColor
}; borderTopWidth: ${this.borderTopWidth}; borderRightWidth: ${
this.borderRightWidth
}; borderBottomWidth: ${this.borderBottomWidth}; borderLeftWidth: ${
this.borderLeftWidth
}; borderTopLeftRadius: ${
this.borderTopLeftRadius
}; borderTopRightRadius: ${
this.borderTopRightRadius
}; borderBottomRightRadius: ${
this.borderBottomRightRadius
}; borderBottomLeftRadius: ${this.borderBottomLeftRadius}; clipPath: ${
this.clipPath
};`;
}
}

View File

@@ -1,7 +1,13 @@
import { View } from "../core/view";
import { LinearGradient } from "./linear-gradient";
import { isDataURI, isFileOrResourcePath, layout, RESOURCE_PREFIX, FILE_PREFIX } from "../../utils/utils";
import {
isDataURI,
isFileOrResourcePath,
layout,
RESOURCE_PREFIX,
FILE_PREFIX,
} from "../../utils/utils";
import { parse } from "../../css-value";
import { path, knownFolders } from "../../file-system";
import * as application from "../../application";
@@ -9,288 +15,367 @@ import { profile } from "../../profiling";
export * from "./background-common";
interface AndroidView {
_cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable;
_cachedDrawable:
| android.graphics.drawable.Drawable.ConstantState
| android.graphics.drawable.Drawable;
}
// TODO: Change this implementation to use
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
let SDK: number;
function getSDK() {
if (!SDK) {
SDK = android.os.Build.VERSION.SDK_INT;
}
let SDK: number;
function getSDK() {
if (!SDK) {
SDK = android.os.Build.VERSION.SDK_INT;
}
return SDK;
}
return SDK;
}
function isSetColorFilterOnlyWidget(nativeView: android.view.View): boolean {
return (
nativeView instanceof android.widget.Button ||
(nativeView instanceof androidx.appcompat.widget.Toolbar
&& getSDK() >= 21 // There is an issue with the DrawableContainer which was fixed for API version 21 and above: https://code.google.com/p/android/issues/detail?id=60183
)
);
}
function isSetColorFilterOnlyWidget(
nativeView: android.view.View
): boolean {
return (
nativeView instanceof android.widget.Button ||
(nativeView instanceof androidx.appcompat.widget.Toolbar &&
getSDK() >= 21) // There is an issue with the DrawableContainer which was fixed for API version 21 and above: https://code.google.com/p/android/issues/detail?id=60183
);
}
export function onBackgroundOrBorderPropertyChanged(view: View) {
const nativeView = <android.view.View>view.nativeViewProtected;
if (!nativeView) {
return;
}
export function onBackgroundOrBorderPropertyChanged(view: View) {
const nativeView = <android.view.View>view.nativeViewProtected;
if (!nativeView) {
return;
}
const background = view.style.backgroundInternal;
let drawable = nativeView.getBackground();
const androidView = <any>view as AndroidView;
// use undefined as not set. getBackground will never return undefined only Drawable or null;
if (androidView._cachedDrawable === undefined && drawable) {
const constantState = drawable.getConstantState();
androidView._cachedDrawable = constantState || drawable;
}
const background = view.style.backgroundInternal;
let drawable = nativeView.getBackground();
const androidView = (<any>view) as AndroidView;
// use undefined as not set. getBackground will never return undefined only Drawable or null;
if (androidView._cachedDrawable === undefined && drawable) {
const constantState = drawable.getConstantState();
androidView._cachedDrawable = constantState || drawable;
}
if (isSetColorFilterOnlyWidget(nativeView)
&& drawable
&& !background.hasBorderWidth()
&& !background.hasBorderRadius()
&& !background.clipPath
&& !background.image
&& background.color) {
if (
isSetColorFilterOnlyWidget(nativeView) &&
drawable &&
!background.hasBorderWidth() &&
!background.hasBorderRadius() &&
!background.clipPath &&
!background.image &&
background.color
) {
if (
drawable instanceof org.nativescript.widgets.BorderDrawable &&
androidView._cachedDrawable
) {
if (
!(
androidView._cachedDrawable instanceof
android.graphics.drawable.Drawable.ConstantState
)
) {
return;
}
if (drawable instanceof org.nativescript.widgets.BorderDrawable && androidView._cachedDrawable) {
if (!(androidView._cachedDrawable instanceof android.graphics.drawable.Drawable.ConstantState)) {
return;
}
drawable = androidView._cachedDrawable.newDrawable(
nativeView.getResources()
);
nativeView.setBackground(drawable);
}
drawable = androidView._cachedDrawable.newDrawable(nativeView.getResources());
nativeView.setBackground(drawable);
}
const backgroundColor = ((<any>drawable).backgroundColor =
background.color.android);
drawable.mutate();
drawable.setColorFilter(
backgroundColor,
android.graphics.PorterDuff.Mode.SRC_IN
);
drawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar
(<any>drawable).backgroundColor = backgroundColor;
} else if (!background.isEmpty()) {
let backgroundDrawable = drawable as org.nativescript.widgets.BorderDrawable;
if (
!(drawable instanceof org.nativescript.widgets.BorderDrawable)
) {
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(
layout.getDisplayDensity(),
view.toString()
);
refreshBorderDrawable(view, backgroundDrawable);
nativeView.setBackground(backgroundDrawable);
} else {
refreshBorderDrawable(view, backgroundDrawable);
}
} else {
const cachedDrawable = androidView._cachedDrawable;
let defaultDrawable: android.graphics.drawable.Drawable = null;
if (cachedDrawable) {
if (
cachedDrawable instanceof
android.graphics.drawable.Drawable.ConstantState
) {
defaultDrawable = cachedDrawable.newDrawable(
nativeView.getResources()
);
} else if (
cachedDrawable instanceof android.graphics.drawable.Drawable
) {
defaultDrawable = cachedDrawable;
}
}
const backgroundColor = (<any>drawable).backgroundColor = background.color.android;
drawable.mutate();
drawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN);
drawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar
(<any>drawable).backgroundColor = backgroundColor;
} else if (!background.isEmpty()) {
let backgroundDrawable = drawable as org.nativescript.widgets.BorderDrawable;
if (!(drawable instanceof org.nativescript.widgets.BorderDrawable)) {
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), view.toString());
refreshBorderDrawable(view, backgroundDrawable);
nativeView.setBackground(backgroundDrawable);
} else {
refreshBorderDrawable(view, backgroundDrawable);
}
} else {
const cachedDrawable = androidView._cachedDrawable;
let defaultDrawable: android.graphics.drawable.Drawable = null;
if (cachedDrawable) {
if (cachedDrawable instanceof android.graphics.drawable.Drawable.ConstantState) {
defaultDrawable = cachedDrawable.newDrawable(nativeView.getResources());
} else if (cachedDrawable instanceof android.graphics.drawable.Drawable) {
defaultDrawable = cachedDrawable;
}
}
nativeView.setBackground(defaultDrawable);
}
nativeView.setBackground(defaultDrawable);
}
// TODO: Can we move BorderWidths as separate native setter?
// This way we could skip setPadding if borderWidth is not changed.
const leftPadding = Math.ceil(
view.effectiveBorderLeftWidth + view.effectivePaddingLeft
);
const topPadding = Math.ceil(
view.effectiveBorderTopWidth + view.effectivePaddingTop
);
const rightPadding = Math.ceil(
view.effectiveBorderRightWidth + view.effectivePaddingRight
);
const bottomPadding = Math.ceil(
view.effectiveBorderBottomWidth + view.effectivePaddingBottom
);
// TODO: Can we move BorderWidths as separate native setter?
// This way we could skip setPadding if borderWidth is not changed.
const leftPadding = Math.ceil(view.effectiveBorderLeftWidth + view.effectivePaddingLeft);
const topPadding = Math.ceil(view.effectiveBorderTopWidth + view.effectivePaddingTop);
const rightPadding = Math.ceil(view.effectiveBorderRightWidth + view.effectivePaddingRight);
const bottomPadding = Math.ceil(view.effectiveBorderBottomWidth + view.effectivePaddingBottom);
nativeView.setPadding(
leftPadding,
topPadding,
rightPadding,
bottomPadding
);
}
nativeView.setPadding(
leftPadding,
topPadding,
rightPadding,
bottomPadding
);
}
}
function fromBase64(source: string): android.graphics.Bitmap {
const bytes = android.util.Base64.decode(source, android.util.Base64.DEFAULT);
const bytes = android.util.Base64.decode(
source,
android.util.Base64.DEFAULT
);
return android.graphics.BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
return android.graphics.BitmapFactory.decodeByteArray(
bytes,
0,
bytes.length
);
}
function fromGradient(gradient: LinearGradient): org.nativescript.widgets.LinearGradientDefinition {
const colors = Array.create("int", gradient.colorStops.length);
const stops = Array.create("float", gradient.colorStops.length);
let hasStops = false;
gradient.colorStops.forEach((stop, index) => {
colors[index] = stop.color.android;
if (stop.offset) {
stops[index] = stop.offset.value;
hasStops = true;
}
});
function fromGradient(
gradient: LinearGradient
): org.nativescript.widgets.LinearGradientDefinition {
const colors = Array.create("int", gradient.colorStops.length);
const stops = Array.create("float", gradient.colorStops.length);
let hasStops = false;
gradient.colorStops.forEach((stop, index) => {
colors[index] = stop.color.android;
if (stop.offset) {
stops[index] = stop.offset.value;
hasStops = true;
}
});
const alpha = gradient.angle / (Math.PI * 2);
const startX = Math.pow(
Math.sin(Math.PI * (alpha + 0.75)),
2
);
const startY = Math.pow(
Math.sin(Math.PI * (alpha + 0.5)),
2
);
const endX = Math.pow(
Math.sin(Math.PI * (alpha + 0.25)),
2
);
const endY = Math.pow(
Math.sin(Math.PI * alpha),
2
);
const alpha = gradient.angle / (Math.PI * 2);
const startX = Math.pow(Math.sin(Math.PI * (alpha + 0.75)), 2);
const startY = Math.pow(Math.sin(Math.PI * (alpha + 0.5)), 2);
const endX = Math.pow(Math.sin(Math.PI * (alpha + 0.25)), 2);
const endY = Math.pow(Math.sin(Math.PI * alpha), 2);
return new org.nativescript.widgets.LinearGradientDefinition(startX, startY, endX, endY, colors, hasStops ? stops : null);
return new org.nativescript.widgets.LinearGradientDefinition(
startX,
startY,
endX,
endY,
colors,
hasStops ? stops : null
);
}
const pattern: RegExp = /url\(('|")(.*?)\1\)/;
function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativescript.widgets.BorderDrawable) {
const nativeView = <android.view.View>view.nativeViewProtected;
const context = nativeView.getContext();
function refreshBorderDrawable(
this: void,
view: View,
borderDrawable: org.nativescript.widgets.BorderDrawable
) {
const nativeView = <android.view.View>view.nativeViewProtected;
const context = nativeView.getContext();
const background = view.style.backgroundInternal;
if (background) {
const backgroundPositionParsedCSSValues = createNativeCSSValueArray(background.position);
const backgroundSizeParsedCSSValues = createNativeCSSValueArray(background.size);
const blackColor = -16777216; //android.graphics.Color.BLACK;
const background = view.style.backgroundInternal;
if (background) {
const backgroundPositionParsedCSSValues = createNativeCSSValueArray(
background.position
);
const backgroundSizeParsedCSSValues = createNativeCSSValueArray(
background.size
);
const blackColor = -16777216; //android.graphics.Color.BLACK;
let imageUri: string;
if (background.image && typeof background.image === "string") {
imageUri = background.image;
const match = imageUri.match(pattern);
if (match && match[2]) {
imageUri = match[2];
}
}
let imageUri: string;
if (background.image && typeof background.image === "string") {
imageUri = background.image;
const match = imageUri.match(pattern);
if (match && match[2]) {
imageUri = match[2];
}
}
let bitmap: android.graphics.Bitmap = null;
if (isDataURI(imageUri)) {
const base64Data = imageUri.split(",")[1];
if (base64Data !== undefined) {
bitmap = fromBase64(base64Data);
imageUri = null;
}
} else if (isFileOrResourcePath(imageUri)) {
if (imageUri.indexOf(RESOURCE_PREFIX) !== 0) {
let fileName = imageUri;
if (fileName.indexOf("~/") === 0) {
fileName = path.join(knownFolders.currentApp().path, fileName.replace("~/", ""));
}
let bitmap: android.graphics.Bitmap = null;
if (isDataURI(imageUri)) {
const base64Data = imageUri.split(",")[1];
if (base64Data !== undefined) {
bitmap = fromBase64(base64Data);
imageUri = null;
}
} else if (isFileOrResourcePath(imageUri)) {
if (imageUri.indexOf(RESOURCE_PREFIX) !== 0) {
let fileName = imageUri;
if (fileName.indexOf("~/") === 0) {
fileName = path.join(
knownFolders.currentApp().path,
fileName.replace("~/", "")
);
}
imageUri = FILE_PREFIX + fileName;
}
}
imageUri = FILE_PREFIX + fileName;
}
}
let gradient: org.nativescript.widgets.LinearGradientDefinition = null;
if (background.image && background.image instanceof LinearGradient) {
gradient = fromGradient(background.image);
}
let gradient: org.nativescript.widgets.LinearGradientDefinition = null;
if (background.image && background.image instanceof LinearGradient) {
gradient = fromGradient(background.image);
}
borderDrawable.refresh(
background.borderTopColor ? background.borderTopColor.android : blackColor,
background.borderRightColor ? background.borderRightColor.android : blackColor,
background.borderBottomColor ? background.borderBottomColor.android : blackColor,
background.borderLeftColor ? background.borderLeftColor.android : blackColor,
borderDrawable.refresh(
background.borderTopColor
? background.borderTopColor.android
: blackColor,
background.borderRightColor
? background.borderRightColor.android
: blackColor,
background.borderBottomColor
? background.borderBottomColor.android
: blackColor,
background.borderLeftColor
? background.borderLeftColor.android
: blackColor,
background.borderTopWidth,
background.borderRightWidth,
background.borderBottomWidth,
background.borderLeftWidth,
background.borderTopWidth,
background.borderRightWidth,
background.borderBottomWidth,
background.borderLeftWidth,
background.borderTopLeftRadius,
background.borderTopRightRadius,
background.borderBottomRightRadius,
background.borderBottomLeftRadius,
background.borderTopLeftRadius,
background.borderTopRightRadius,
background.borderBottomRightRadius,
background.borderBottomLeftRadius,
background.clipPath,
background.clipPath,
background.color ? background.color.android : 0,
imageUri,
bitmap,
gradient,
context,
background.repeat,
background.position,
backgroundPositionParsedCSSValues,
background.size,
backgroundSizeParsedCSSValues
);
//console.log(`>>> ${borderDrawable.toDebugString()}`);
}
background.color ? background.color.android : 0,
imageUri,
bitmap,
gradient,
context,
background.repeat,
background.position,
backgroundPositionParsedCSSValues,
background.size,
backgroundSizeParsedCSSValues
);
//console.log(`>>> ${borderDrawable.toDebugString()}`);
}
}
function createNativeCSSValueArray(css: string): native.Array<org.nativescript.widgets.CSSValue> {
if (!css) {
return null;
}
function createNativeCSSValueArray(
css: string
): native.Array<org.nativescript.widgets.CSSValue> {
if (!css) {
return null;
}
const cssValues = parse(css);
const nativeArray = Array.create(org.nativescript.widgets.CSSValue, cssValues.length);
for (let i = 0, length = cssValues.length; i < length; i++) {
nativeArray[i] = new org.nativescript.widgets.CSSValue(
cssValues[i].type,
cssValues[i].string,
cssValues[i].unit,
cssValues[i].value
);
}
const cssValues = parse(css);
const nativeArray = Array.create(
org.nativescript.widgets.CSSValue,
cssValues.length
);
for (let i = 0, length = cssValues.length; i < length; i++) {
nativeArray[i] = new org.nativescript.widgets.CSSValue(
cssValues[i].type,
cssValues[i].string,
cssValues[i].unit,
cssValues[i].value
);
}
return nativeArray;
return nativeArray;
}
export enum CacheMode {
none,
memory,
diskAndMemory
none,
memory,
diskAndMemory,
}
let currentCacheMode: CacheMode;
let imageFetcher: org.nativescript.widgets.image.Fetcher;
export function initImageCache(context: android.content.Context, mode = CacheMode.diskAndMemory, memoryCacheSize: number = 0.25, diskCacheSize: number = 10 * 1024 * 1024): void {
if (currentCacheMode === mode) {
return;
}
export function initImageCache(
context: android.content.Context,
mode = CacheMode.diskAndMemory,
memoryCacheSize: number = 0.25,
diskCacheSize: number = 10 * 1024 * 1024
): void {
if (currentCacheMode === mode) {
return;
}
currentCacheMode = mode;
if (!imageFetcher) {
imageFetcher = org.nativescript.widgets.image.Fetcher.getInstance(context);
} else {
imageFetcher.clearCache();
}
currentCacheMode = mode;
if (!imageFetcher) {
imageFetcher = org.nativescript.widgets.image.Fetcher.getInstance(
context
);
} else {
imageFetcher.clearCache();
}
const params = new org.nativescript.widgets.image.Cache.CacheParams();
params.memoryCacheEnabled = mode !== CacheMode.none;
params.setMemCacheSizePercent(memoryCacheSize); // Set memory cache to % of app memory
params.diskCacheEnabled = mode === CacheMode.diskAndMemory;
params.diskCacheSize = diskCacheSize;
const imageCache = org.nativescript.widgets.image.Cache.getInstance(params);
imageFetcher.addImageCache(imageCache);
imageFetcher.initCache();
const params = new org.nativescript.widgets.image.Cache.CacheParams();
params.memoryCacheEnabled = mode !== CacheMode.none;
params.setMemCacheSizePercent(memoryCacheSize); // Set memory cache to % of app memory
params.diskCacheEnabled = mode === CacheMode.diskAndMemory;
params.diskCacheSize = diskCacheSize;
const imageCache = org.nativescript.widgets.image.Cache.getInstance(params);
imageFetcher.addImageCache(imageCache);
imageFetcher.initCache();
}
function onLivesync(args): void {
if (imageFetcher) {
imageFetcher.clearCache();
}
if (imageFetcher) {
imageFetcher.clearCache();
}
}
application.on("livesync", onLivesync);
application.android.on("activityStarted", <any>profile("initImageCache", args => {
if (!imageFetcher) {
initImageCache(args.activity);
} else {
imageFetcher.initCache();
}
}));
application.android.on(
"activityStarted",
<any>profile("initImageCache", (args) => {
if (!imageFetcher) {
initImageCache(args.activity);
} else {
imageFetcher.initCache();
}
})
);
application.android.on("activityStopped", <any>profile("closeImageCache", args => {
if (imageFetcher) {
imageFetcher.closeCache();
}
}));
application.android.on(
"activityStopped",
<any>profile("closeImageCache", (args) => {
if (imageFetcher) {
imageFetcher.closeCache();
}
})
);

View File

@@ -4,65 +4,69 @@ import { BackgroundRepeat } from "../../css/parser";
import { LinearGradient } from "../styling/linear-gradient";
export class Background {
public static default: Background;
public color: Color;
public image: string | LinearGradient;
public repeat: BackgroundRepeat;
public position: string;
public size: string;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderTopWidth: number;
public borderRightWidth: number;
public borderBottomWidth: number;
public borderLeftWidth: number;
public borderTopLeftRadius: number;
public borderTopRightRadius: number;
public borderBottomRightRadius: number;
public borderBottomLeftRadius: number;
public clipPath: string;
public static default: Background;
public color: Color;
public image: string | LinearGradient;
public repeat: BackgroundRepeat;
public position: string;
public size: string;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderTopWidth: number;
public borderRightWidth: number;
public borderBottomWidth: number;
public borderLeftWidth: number;
public borderTopLeftRadius: number;
public borderTopRightRadius: number;
public borderBottomRightRadius: number;
public borderBottomLeftRadius: number;
public clipPath: string;
public withColor(value: Color): Background;
public withImage(value: string | LinearGradient): Background;
public withRepeat(value: BackgroundRepeat): Background;
public withPosition(value: string): Background;
public withSize(value: string): Background;
public withBorderTopColor(value: Color): Background;
public withBorderRightColor(value: Color): Background;
public withBorderBottomColor(value: Color): Background;
public withBorderLeftColor(value: Color): Background;
public withBorderTopWidth(value: number): Background;
public withBorderRightWidth(value: number): Background;
public withBorderBottomWidth(value: number): Background;
public withBorderLeftWidth(value: number): Background;
public withBorderTopLeftRadius(value: number): Background;
public withBorderTopRightRadius(value: number): Background;
public withBorderBottomRightRadius(value: number): Background;
public withBorderBottomLeftRadius(value: number): Background;
public withClipPath(value: string): Background;
public withColor(value: Color): Background;
public withImage(value: string | LinearGradient): Background;
public withRepeat(value: BackgroundRepeat): Background;
public withPosition(value: string): Background;
public withSize(value: string): Background;
public withBorderTopColor(value: Color): Background;
public withBorderRightColor(value: Color): Background;
public withBorderBottomColor(value: Color): Background;
public withBorderLeftColor(value: Color): Background;
public withBorderTopWidth(value: number): Background;
public withBorderRightWidth(value: number): Background;
public withBorderBottomWidth(value: number): Background;
public withBorderLeftWidth(value: number): Background;
public withBorderTopLeftRadius(value: number): Background;
public withBorderTopRightRadius(value: number): Background;
public withBorderBottomRightRadius(value: number): Background;
public withBorderBottomLeftRadius(value: number): Background;
public withClipPath(value: string): Background;
public isEmpty(): boolean;
public isEmpty(): boolean;
public static equals(value1: Background, value2: Background): boolean;
public static equals(value1: Background, value2: Background): boolean;
public hasBorderColor(): boolean;
public hasBorderWidth(): boolean;
public hasBorderRadius(): boolean;
public hasUniformBorderColor(): boolean;
public hasUniformBorderWidth(): boolean;
public hasUniformBorderRadius(): boolean;
public hasUniformBorder(): boolean;
public getUniformBorderColor(): Color;
public getUniformBorderWidth(): number;
public getUniformBorderRadius(): number;
public hasBorderColor(): boolean;
public hasBorderWidth(): boolean;
public hasBorderRadius(): boolean;
public hasUniformBorderColor(): boolean;
public hasUniformBorderWidth(): boolean;
public hasUniformBorderRadius(): boolean;
public hasUniformBorder(): boolean;
public getUniformBorderColor(): Color;
public getUniformBorderWidth(): number;
public getUniformBorderRadius(): number;
}
export module ios {
export function createBackgroundUIColor(view: View, callback: (uiColor: any /* UIColor */) => void, flip?: boolean): void;
export function createBackgroundUIColor(
view: View,
callback: (uiColor: any /* UIColor */) => void,
flip?: boolean
): void;
}
export module ad {
export function onBackgroundOrBorderPropertyChanged(v: View);
export function onBackgroundOrBorderPropertyChanged(v: View);
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +1,54 @@
import { AnimationCurve } from "../enums";
const STYLE_CURVE_MAP = Object.freeze({
"ease": AnimationCurve.ease,
"linear": AnimationCurve.linear,
"ease-in": AnimationCurve.easeIn,
"ease-out": AnimationCurve.easeOut,
"ease-in-out": AnimationCurve.easeInOut,
"spring": AnimationCurve.spring,
ease: AnimationCurve.ease,
linear: AnimationCurve.linear,
"ease-in": AnimationCurve.easeIn,
"ease-out": AnimationCurve.easeOut,
"ease-in-out": AnimationCurve.easeInOut,
spring: AnimationCurve.spring,
});
export function timeConverter(value: string): number {
let result = parseFloat(value);
if (value.indexOf("ms") === -1) {
result = result * 1000;
}
let result = parseFloat(value);
if (value.indexOf("ms") === -1) {
result = result * 1000;
}
return Math.max(0.0, result);
return Math.max(0.0, result);
}
export function animationTimingFunctionConverter(value: string): any {
return value ?
STYLE_CURVE_MAP[value] || parseCubicBezierCurve(value) :
AnimationCurve.ease;
return value
? STYLE_CURVE_MAP[value] || parseCubicBezierCurve(value)
: AnimationCurve.ease;
}
function parseCubicBezierCurve(value: string) {
const coordsString = /\((.*?)\)/.exec(value);
const coords = coordsString && coordsString[1]
.split(",")
.map(stringToBezieCoords);
const coordsString = /\((.*?)\)/.exec(value);
const coords =
coordsString && coordsString[1].split(",").map(stringToBezieCoords);
if (value.startsWith("cubic-bezier") &&
coordsString &&
coords.length === 4) {
if (
value.startsWith("cubic-bezier") &&
coordsString &&
coords.length === 4
) {
const [x1, x2, y1, y2] = [...coords];
const [x1, x2, y1, y2] = [...coords];
return AnimationCurve.cubicBezier(x1, x2, y1, y2);
} else {
throw new Error(`Invalid value for animation: ${value}`);
}
return AnimationCurve.cubicBezier(x1, x2, y1, y2);
} else {
throw new Error(`Invalid value for animation: ${value}`);
}
}
function stringToBezieCoords(value: string): number {
let result = parseFloat(value);
if (result < 0) {
return 0;
} else if (result > 1) {
return 1;
}
let result = parseFloat(value);
if (result < 0) {
return 0;
} else if (result > 1) {
return 1;
}
return result;
return result;
}

View File

@@ -1,14 +1,20 @@
import {
KeyframeAnimationInfo,
KeyframeDeclaration,
KeyframeInfo,
UnparsedKeyframe,
KeyframeAnimationInfo,
KeyframeDeclaration,
KeyframeInfo,
UnparsedKeyframe,
} from "../animation/keyframe-animation";
export class CssAnimationParser {
public static keyframeAnimationsFromCSSDeclarations(declarations: KeyframeDeclaration[]): KeyframeAnimationInfo[];
public static keyframeAnimationsFromCSSDeclarations(
declarations: KeyframeDeclaration[]
): KeyframeAnimationInfo[];
public static keyframesArrayFromCSS(keyframes: UnparsedKeyframe[]): KeyframeInfo[];
public static keyframesArrayFromCSS(
keyframes: UnparsedKeyframe[]
): KeyframeInfo[];
}
export function parseKeyframeDeclarations(unparsedKeyframeDeclarations: KeyframeDeclaration[]) : KeyframeDeclaration[];
export function parseKeyframeDeclarations(
unparsedKeyframeDeclarations: KeyframeDeclaration[]
): KeyframeDeclaration[];

View File

@@ -1,147 +1,186 @@
import { CssAnimationProperty } from "../core/properties";
import {
KeyframeAnimationInfo,
KeyframeDeclaration,
KeyframeInfo,
UnparsedKeyframe,
KeyframeAnimationInfo,
KeyframeDeclaration,
KeyframeInfo,
UnparsedKeyframe,
} from "../animation/keyframe-animation";
import { timeConverter, animationTimingFunctionConverter } from "../styling/converters";
import {
timeConverter,
animationTimingFunctionConverter,
} from "../styling/converters";
import { transformConverter } from "../styling/style-properties";
const ANIMATION_PROPERTY_HANDLERS = Object.freeze({
"animation-name": (info: any, value: any) => info.name = value,
"animation-duration": (info: any, value: any) => info.duration = timeConverter(value),
"animation-delay": (info: any, value: any) => info.delay = timeConverter(value),
"animation-timing-function": (info: any, value: any) => info.curve = animationTimingFunctionConverter(value),
"animation-iteration-count": (info: any, value: any) => info.iterations = value === "infinite" ? Number.MAX_VALUE : parseFloat(value),
"animation-direction": (info: any, value: any) => info.isReverse = value === "reverse",
"animation-fill-mode": (info: any, value: any) => info.isForwards = value === "forwards"
"animation-name": (info: any, value: any) => (info.name = value),
"animation-duration": (info: any, value: any) =>
(info.duration = timeConverter(value)),
"animation-delay": (info: any, value: any) =>
(info.delay = timeConverter(value)),
"animation-timing-function": (info: any, value: any) =>
(info.curve = animationTimingFunctionConverter(value)),
"animation-iteration-count": (info: any, value: any) =>
(info.iterations =
value === "infinite" ? Number.MAX_VALUE : parseFloat(value)),
"animation-direction": (info: any, value: any) =>
(info.isReverse = value === "reverse"),
"animation-fill-mode": (info: any, value: any) =>
(info.isForwards = value === "forwards"),
});
export class CssAnimationParser {
public static keyframeAnimationsFromCSSDeclarations(declarations: KeyframeDeclaration[])
: KeyframeAnimationInfo[] {
public static keyframeAnimationsFromCSSDeclarations(
declarations: KeyframeDeclaration[]
): KeyframeAnimationInfo[] {
if (declarations === null || declarations === undefined) {
return undefined;
}
if (declarations === null || declarations === undefined) {
return undefined;
}
let animations = new Array<KeyframeAnimationInfo>();
let animationInfo: KeyframeAnimationInfo = undefined;
let animations = new Array<KeyframeAnimationInfo>();
let animationInfo: KeyframeAnimationInfo = undefined;
declarations.forEach(({ property, value }) => {
if (property === "animation") {
keyframeAnimationsFromCSSProperty(value, animations);
} else {
const propertyHandler = ANIMATION_PROPERTY_HANDLERS[property];
if (propertyHandler) {
if (animationInfo === undefined) {
animationInfo = new KeyframeAnimationInfo();
animations.push(animationInfo);
}
propertyHandler(animationInfo, value);
}
}
});
declarations.forEach(({ property, value }) => {
if (property === "animation") {
keyframeAnimationsFromCSSProperty(value, animations);
} else {
const propertyHandler = ANIMATION_PROPERTY_HANDLERS[property];
if (propertyHandler) {
if (animationInfo === undefined) {
animationInfo = new KeyframeAnimationInfo();
animations.push(animationInfo);
}
propertyHandler(animationInfo, value);
}
}
});
return animations.length === 0 ? undefined : animations;
}
return animations.length === 0 ? undefined : animations;
}
public static keyframesArrayFromCSS(
keyframes: UnparsedKeyframe[]
): KeyframeInfo[] {
let parsedKeyframes = new Array<KeyframeInfo>();
for (let keyframe of keyframes) {
let declarations = parseKeyframeDeclarations(keyframe.declarations);
for (let time of keyframe.values) {
if (time === "from") {
time = 0;
} else if (time === "to") {
time = 1;
} else {
time = parseFloat(time) / 100;
if (time < 0) {
time = 0;
}
if (time > 100) {
time = 100;
}
}
let current = parsedKeyframes[time];
if (current === undefined) {
current = <KeyframeInfo>{};
current.duration = time;
parsedKeyframes[time] = current;
}
for (let declaration of keyframe.declarations) {
if (declaration.property === "animation-timing-function") {
current.curve = animationTimingFunctionConverter(
declaration.value
);
}
}
current.declarations = declarations;
}
}
let array = new Array();
for (let parsedKeyframe in parsedKeyframes) {
array.push(parsedKeyframes[parsedKeyframe]);
}
array.sort(function (a, b) {
return a.duration - b.duration;
});
public static keyframesArrayFromCSS(keyframes: UnparsedKeyframe[]): KeyframeInfo[] {
let parsedKeyframes = new Array<KeyframeInfo>();
for (let keyframe of keyframes) {
let declarations = parseKeyframeDeclarations(keyframe.declarations);
for (let time of keyframe.values) {
if (time === "from") {
time = 0;
} else if (time === "to") {
time = 1;
} else {
time = parseFloat(time) / 100;
if (time < 0) {
time = 0;
}
if (time > 100) {
time = 100;
}
}
let current = parsedKeyframes[time];
if (current === undefined) {
current = <KeyframeInfo>{};
current.duration = time;
parsedKeyframes[time] = current;
}
for (let declaration of keyframe.declarations) {
if (declaration.property === "animation-timing-function") {
current.curve = animationTimingFunctionConverter(declaration.value);
}
}
current.declarations = declarations;
}
}
let array = new Array();
for (let parsedKeyframe in parsedKeyframes) {
array.push(parsedKeyframes[parsedKeyframe]);
}
array.sort(function (a, b) { return a.duration - b.duration; });
return array;
}
return array;
}
}
function keyframeAnimationsFromCSSProperty(value: any, animations: KeyframeAnimationInfo[]) {
if (typeof value === "string") {
let values = value.split(/[,]+/);
for (let parsedValue of values) {
let animationInfo = new KeyframeAnimationInfo();
let arr = (<string>parsedValue).trim().split(/[ ]+/);
function keyframeAnimationsFromCSSProperty(
value: any,
animations: KeyframeAnimationInfo[]
) {
if (typeof value === "string") {
let values = value.split(/[,]+/);
for (let parsedValue of values) {
let animationInfo = new KeyframeAnimationInfo();
let arr = (<string>parsedValue).trim().split(/[ ]+/);
if (arr.length > 0) {
animationInfo.name = arr[0];
}
if (arr.length > 1) {
animationInfo.duration = timeConverter(arr[1]);
}
if (arr.length > 2) {
animationInfo.curve = animationTimingFunctionConverter(arr[2]);
}
if (arr.length > 3) {
animationInfo.delay = timeConverter(arr[3]);
}
if (arr.length > 4) {
animationInfo.iterations = parseInt(arr[4]);
}
if (arr.length > 5) {
animationInfo.isReverse = arr[4] === "reverse";
}
if (arr.length > 6) {
animationInfo.isForwards = arr[5] === "forwards";
}
if (arr.length > 7) {
throw new Error("Invalid value for animation: " + value);
}
animations.push(animationInfo);
}
}
if (arr.length > 0) {
animationInfo.name = arr[0];
}
if (arr.length > 1) {
animationInfo.duration = timeConverter(arr[1]);
}
if (arr.length > 2) {
animationInfo.curve = animationTimingFunctionConverter(arr[2]);
}
if (arr.length > 3) {
animationInfo.delay = timeConverter(arr[3]);
}
if (arr.length > 4) {
animationInfo.iterations = parseInt(arr[4]);
}
if (arr.length > 5) {
animationInfo.isReverse = arr[4] === "reverse";
}
if (arr.length > 6) {
animationInfo.isForwards = arr[5] === "forwards";
}
if (arr.length > 7) {
throw new Error("Invalid value for animation: " + value);
}
animations.push(animationInfo);
}
}
}
export function parseKeyframeDeclarations(unparsedKeyframeDeclarations: KeyframeDeclaration[]): KeyframeDeclaration[] {
export function parseKeyframeDeclarations(
unparsedKeyframeDeclarations: KeyframeDeclaration[]
): KeyframeDeclaration[] {
const declarations = unparsedKeyframeDeclarations.reduce(
(
declarations,
{ property: unparsedProperty, value: unparsedValue }
) => {
const property = CssAnimationProperty._getByCssName(
unparsedProperty
);
const declarations = unparsedKeyframeDeclarations
.reduce((declarations, { property: unparsedProperty, value: unparsedValue }) => {
const property = CssAnimationProperty._getByCssName(unparsedProperty);
if (
typeof unparsedProperty === "string" &&
property &&
property._valueConverter
) {
declarations[property.name] = property._valueConverter(
<string>unparsedValue
);
} else if (
typeof unparsedValue === "string" &&
unparsedProperty === "transform"
) {
const transformations = transformConverter(unparsedValue);
Object.assign(declarations, transformations);
}
if (typeof unparsedProperty === "string" && property && property._valueConverter) {
declarations[property.name] = property._valueConverter(<string>unparsedValue);
} else if (typeof unparsedValue === "string" && unparsedProperty === "transform") {
const transformations = transformConverter(unparsedValue);
Object.assign(declarations, transformations);
}
return declarations;
},
{}
);
return declarations;
}, {});
return Object.keys(declarations).map(property => ({ property, value: declarations[property] }));
return Object.keys(declarations).map((property) => ({
property,
value: declarations[property],
}));
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -5,104 +5,128 @@ import { makeValidator, makeParser } from "../core/properties";
export * from "./font-interfaces";
export abstract class Font implements FontDefinition {
public static default = undefined;
public static default = undefined;
get isItalic(): boolean {
return this.fontStyle === FontStyle.ITALIC;
}
get isItalic(): boolean {
return this.fontStyle === FontStyle.ITALIC;
}
get isBold(): boolean {
return this.fontWeight === FontWeight.SEMI_BOLD ||
this.fontWeight === FontWeight.BOLD ||
this.fontWeight === "700" ||
this.fontWeight === FontWeight.EXTRA_BOLD ||
this.fontWeight === FontWeight.BLACK;
}
get isBold(): boolean {
return (
this.fontWeight === FontWeight.SEMI_BOLD ||
this.fontWeight === FontWeight.BOLD ||
this.fontWeight === "700" ||
this.fontWeight === FontWeight.EXTRA_BOLD ||
this.fontWeight === FontWeight.BLACK
);
}
protected constructor(
public readonly fontFamily: string,
public readonly fontSize: number,
public readonly fontStyle: FontStyle,
public readonly fontWeight: FontWeight) {
}
protected constructor(
public readonly fontFamily: string,
public readonly fontSize: number,
public readonly fontStyle: FontStyle,
public readonly fontWeight: FontWeight
) {}
public abstract getAndroidTypeface(): any /* android.graphics.Typeface */;
public abstract getUIFont(defaultFont: any /* UIFont */): any /* UIFont */;
public abstract withFontFamily(family: string): Font;
public abstract withFontStyle(style: string): Font;
public abstract withFontWeight(weight: string): Font;
public abstract withFontSize(size: number): Font;
public abstract getAndroidTypeface(): any /* android.graphics.Typeface */;
public abstract getUIFont(defaultFont: any /* UIFont */): any /* UIFont */;
public abstract withFontFamily(family: string): Font;
public abstract withFontStyle(style: string): Font;
public abstract withFontWeight(weight: string): Font;
public abstract withFontSize(size: number): Font;
public static equals(value1: Font, value2: Font): boolean {
// both values are falsy
if (!value1 && !value2) {
return true;
}
public static equals(value1: Font, value2: Font): boolean {
// both values are falsy
if (!value1 && !value2) {
return true;
}
// only one is falsy
if (!value1 || !value2) {
return false;
}
// only one is falsy
if (!value1 || !value2) {
return false;
}
return value1.fontFamily === value2.fontFamily &&
value1.fontSize === value2.fontSize &&
value1.fontStyle === value2.fontStyle &&
value1.fontWeight === value2.fontWeight;
}
return (
value1.fontFamily === value2.fontFamily &&
value1.fontSize === value2.fontSize &&
value1.fontStyle === value2.fontStyle &&
value1.fontWeight === value2.fontWeight
);
}
}
export type FontStyle = "normal" | "italic";
export namespace FontStyle {
export const NORMAL: "normal" = "normal";
export const ITALIC: "italic" = "italic";
export const isValid = makeValidator<FontStyle>(NORMAL, ITALIC);
export const parse = makeParser<FontStyle>(isValid);
export const NORMAL: "normal" = "normal";
export const ITALIC: "italic" = "italic";
export const isValid = makeValidator<FontStyle>(NORMAL, ITALIC);
export const parse = makeParser<FontStyle>(isValid);
}
export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export type FontWeight =
| "100"
| "200"
| "300"
| "normal"
| "400"
| "500"
| "600"
| "bold"
| "700"
| "800"
| "900";
export namespace FontWeight {
export const THIN: "100" = "100";
export const EXTRA_LIGHT: "200" = "200";
export const LIGHT: "300" = "300";
export const NORMAL: "normal" = "normal";
export const MEDIUM: "500" = "500";
export const SEMI_BOLD: "600" = "600";
export const BOLD: "bold" = "bold";
export const EXTRA_BOLD: "800" = "800";
export const BLACK: "900" = "900";
export const isValid = makeValidator<FontWeight>(THIN, EXTRA_LIGHT, LIGHT, NORMAL, "400", MEDIUM, SEMI_BOLD, BOLD, "700", EXTRA_BOLD, BLACK);
export const parse = makeParser<FontStyle>(isValid);
export const THIN: "100" = "100";
export const EXTRA_LIGHT: "200" = "200";
export const LIGHT: "300" = "300";
export const NORMAL: "normal" = "normal";
export const MEDIUM: "500" = "500";
export const SEMI_BOLD: "600" = "600";
export const BOLD: "bold" = "bold";
export const EXTRA_BOLD: "800" = "800";
export const BLACK: "900" = "900";
export const isValid = makeValidator<FontWeight>(
THIN,
EXTRA_LIGHT,
LIGHT,
NORMAL,
"400",
MEDIUM,
SEMI_BOLD,
BOLD,
"700",
EXTRA_BOLD,
BLACK
);
export const parse = makeParser<FontStyle>(isValid);
}
export function parseFontFamily(value: string): Array<string> {
const result = new Array<string>();
if (!value) {
return result;
}
const result = new Array<string>();
if (!value) {
return result;
}
const split = value.split(",");
for (let i = 0; i < split.length; i++) {
let str = split[i].trim().replace(/['"]+/g, "");
if (str) {
result.push(str);
}
}
const split = value.split(",");
for (let i = 0; i < split.length; i++) {
let str = split[i].trim().replace(/['"]+/g, "");
if (str) {
result.push(str);
}
}
return result;
return result;
}
export module genericFontFamilies {
export const serif = "serif";
export const sansSerif = "sans-serif";
export const monospace = "monospace";
export const system = "system";
export const serif = "serif";
export const sansSerif = "sans-serif";
export const monospace = "monospace";
export const system = "system";
}
const styles = new Set();
[
FontStyle.NORMAL,
FontStyle.ITALIC
].forEach((val, i, a) => styles.add(val));
[FontStyle.NORMAL, FontStyle.ITALIC].forEach((val, i, a) => styles.add(val));
// http://www.w3schools.com/cssref/pr_font_weight.asp
//- normal(same as 400)
@@ -118,55 +142,50 @@ const styles = new Set();
//- 900(Black / Heavy) (API21 -black)
const weights = new Set();
[
FontWeight.THIN,
FontWeight.EXTRA_LIGHT,
FontWeight.LIGHT,
FontWeight.NORMAL,
"400",
FontWeight.MEDIUM,
FontWeight.SEMI_BOLD,
FontWeight.BOLD,
"700",
FontWeight.EXTRA_BOLD,
FontWeight.BLACK
FontWeight.THIN,
FontWeight.EXTRA_LIGHT,
FontWeight.LIGHT,
FontWeight.NORMAL,
"400",
FontWeight.MEDIUM,
FontWeight.SEMI_BOLD,
FontWeight.BOLD,
"700",
FontWeight.EXTRA_BOLD,
FontWeight.BLACK,
].forEach((val, i, a) => weights.add(val));
export function parseFont(fontValue: string): ParsedFont {
let result: ParsedFont = {
fontStyle: "normal",
fontVariant: "normal",
fontWeight: "normal"
};
let result: ParsedFont = {
fontStyle: "normal",
fontVariant: "normal",
fontWeight: "normal",
};
const parts = fontValue.split(/\s+/);
let part: string;
while (part = parts.shift()) {
if (part === "normal") {
// nothing to do here
}
else if (part === "small-caps") {
// The only supported font variant in shorthand font
result.fontVariant = part;
}
else if (styles.has(part)) {
result.fontStyle = <any>part;
}
else if (weights.has(part)) {
result.fontWeight = <any>part;
}
else if (!result.fontSize) {
let sizes = part.split("/");
result.fontSize = sizes[0];
result.lineHeight = sizes.length > 1 ? sizes[1] : undefined;
}
else {
result.fontFamily = part;
if (parts.length) {
result.fontFamily += " " + parts.join(" ");
}
break;
}
}
const parts = fontValue.split(/\s+/);
let part: string;
while ((part = parts.shift())) {
if (part === "normal") {
// nothing to do here
} else if (part === "small-caps") {
// The only supported font variant in shorthand font
result.fontVariant = part;
} else if (styles.has(part)) {
result.fontStyle = <any>part;
} else if (weights.has(part)) {
result.fontWeight = <any>part;
} else if (!result.fontSize) {
let sizes = part.split("/");
result.fontSize = sizes[0];
result.lineHeight = sizes.length > 1 ? sizes[1] : undefined;
} else {
result.fontFamily = part;
if (parts.length) {
result.fontFamily += " " + parts.join(" ");
}
break;
}
}
return result;
return result;
}

View File

@@ -1,12 +1,23 @@
export type FontStyle = "normal" | "italic";
export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export type FontWeight =
| "100"
| "200"
| "300"
| "normal"
| "400"
| "500"
| "600"
| "bold"
| "700"
| "800"
| "900";
export interface ParsedFont {
fontStyle?: FontStyle;
fontVariant?: string;
fontWeight?: FontWeight;
lineHeight?: string;
fontSize?: string;
fontFamily?: string;
fontStyle?: FontStyle;
fontVariant?: string;
fontWeight?: FontWeight;
lineHeight?: string;
fontSize?: string;
fontFamily?: string;
}

View File

@@ -1,4 +1,9 @@
import { Font as FontBase, parseFontFamily, genericFontFamilies, FontWeight } from "./font-common";
import {
Font as FontBase,
parseFontFamily,
genericFontFamilies,
FontWeight,
} from "./font-common";
import { Trace } from "../../trace";
import * as application from "../../application";
import * as fs from "../../file-system";
@@ -10,154 +15,189 @@ const typefaceCache = new Map<string, android.graphics.Typeface>();
let appAssets: android.content.res.AssetManager;
export class Font extends FontBase {
public static default = new Font(undefined, undefined, "normal", "normal");
public static default = new Font(undefined, undefined, "normal", "normal");
private _typeface: android.graphics.Typeface;
private _typeface: android.graphics.Typeface;
constructor(family: string, size: number, style: "normal" | "italic", weight: FontWeight) {
super(family, size, style, weight);
}
constructor(
family: string,
size: number,
style: "normal" | "italic",
weight: FontWeight
) {
super(family, size, style, weight);
}
public withFontFamily(family: string): Font {
return new Font(family, this.fontSize, this.fontStyle, this.fontWeight);
}
public withFontFamily(family: string): Font {
return new Font(family, this.fontSize, this.fontStyle, this.fontWeight);
}
public withFontStyle(style: "normal" | "italic"): Font {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontStyle(style: "normal" | "italic"): Font {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
public withFontSize(size: number): Font {
return new Font(this.fontFamily, size, this.fontStyle, this.fontWeight);
}
public withFontSize(size: number): Font {
return new Font(this.fontFamily, size, this.fontStyle, this.fontWeight);
}
public getAndroidTypeface(): android.graphics.Typeface {
if (!this._typeface) {
this._typeface = createTypeface(this);
}
public getAndroidTypeface(): android.graphics.Typeface {
if (!this._typeface) {
this._typeface = createTypeface(this);
}
return this._typeface;
}
return this._typeface;
}
public getUIFont(defaultFont: UIFont): UIFont {
return undefined;
}
public getUIFont(defaultFont: UIFont): UIFont {
return undefined;
}
}
function loadFontFromFile(fontFamily: string): android.graphics.Typeface {
appAssets = appAssets || application.android.context.getAssets();
if (!appAssets) {
return null;
}
appAssets = appAssets || application.android.context.getAssets();
if (!appAssets) {
return null;
}
let result = typefaceCache.get(fontFamily);
// Check for undefined explicitly as null mean we tried to load the font, but failed.
if (result === undefined) {
result = null;
let result = typefaceCache.get(fontFamily);
// Check for undefined explicitly as null mean we tried to load the font, but failed.
if (result === undefined) {
result = null;
let fontAssetPath: string;
const basePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFamily);
if (fs.File.exists(basePath + ".ttf")) {
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".ttf";
}
else if (fs.File.exists(basePath + ".otf")) {
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".otf";
}
else {
if (Trace.isEnabled()) {
Trace.write("Could not find font file for " + fontFamily, Trace.categories.Error, Trace.messageType.error);
}
}
let fontAssetPath: string;
const basePath = fs.path.join(
fs.knownFolders.currentApp().path,
"fonts",
fontFamily
);
if (fs.File.exists(basePath + ".ttf")) {
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".ttf";
} else if (fs.File.exists(basePath + ".otf")) {
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".otf";
} else {
if (Trace.isEnabled()) {
Trace.write(
"Could not find font file for " + fontFamily,
Trace.categories.Error,
Trace.messageType.error
);
}
}
if (fontAssetPath) {
try {
fontAssetPath = fs.path.join(fs.knownFolders.currentApp().path, fontAssetPath);
result = android.graphics.Typeface.createFromFile(fontAssetPath);
} catch (e) {
if (Trace.isEnabled()) {
Trace.write("Error loading font asset: " + fontAssetPath, Trace.categories.Error, Trace.messageType.error);
}
}
}
typefaceCache.set(fontFamily, result);
}
if (fontAssetPath) {
try {
fontAssetPath = fs.path.join(
fs.knownFolders.currentApp().path,
fontAssetPath
);
result = android.graphics.Typeface.createFromFile(
fontAssetPath
);
} catch (e) {
if (Trace.isEnabled()) {
Trace.write(
"Error loading font asset: " + fontAssetPath,
Trace.categories.Error,
Trace.messageType.error
);
}
}
}
typefaceCache.set(fontFamily, result);
}
return result;
return result;
}
function createTypeface(font: Font): android.graphics.Typeface {
let fontStyle = 0;
if (font.isBold) {
fontStyle |= android.graphics.Typeface.BOLD;
}
if (font.isItalic) {
fontStyle |= android.graphics.Typeface.ITALIC;
}
let fontStyle = 0;
if (font.isBold) {
fontStyle |= android.graphics.Typeface.BOLD;
}
if (font.isItalic) {
fontStyle |= android.graphics.Typeface.ITALIC;
}
//http://stackoverflow.com/questions/19691530/valid-values-for-androidfontfamily-and-what-they-map-to
const fonts = parseFontFamily(font.fontFamily);
let result = null;
for (let i = 0; i < fonts.length; i++) {
switch (fonts[i].toLowerCase()) {
case genericFontFamilies.serif:
result = android.graphics.Typeface.create("serif" + getFontWeightSuffix(font.fontWeight), fontStyle);
break;
//http://stackoverflow.com/questions/19691530/valid-values-for-androidfontfamily-and-what-they-map-to
const fonts = parseFontFamily(font.fontFamily);
let result = null;
for (let i = 0; i < fonts.length; i++) {
switch (fonts[i].toLowerCase()) {
case genericFontFamilies.serif:
result = android.graphics.Typeface.create(
"serif" + getFontWeightSuffix(font.fontWeight),
fontStyle
);
break;
case genericFontFamilies.sansSerif:
case genericFontFamilies.system:
result = android.graphics.Typeface.create("sans-serif" + getFontWeightSuffix(font.fontWeight), fontStyle);
break;
case genericFontFamilies.sansSerif:
case genericFontFamilies.system:
result = android.graphics.Typeface.create(
"sans-serif" + getFontWeightSuffix(font.fontWeight),
fontStyle
);
break;
case genericFontFamilies.monospace:
result = android.graphics.Typeface.create("monospace" + getFontWeightSuffix(font.fontWeight), fontStyle);
break;
case genericFontFamilies.monospace:
result = android.graphics.Typeface.create(
"monospace" + getFontWeightSuffix(font.fontWeight),
fontStyle
);
break;
default:
result = loadFontFromFile(fonts[i]);
if (result && fontStyle) {
result = android.graphics.Typeface.create(result, fontStyle);
}
break;
}
default:
result = loadFontFromFile(fonts[i]);
if (result && fontStyle) {
result = android.graphics.Typeface.create(
result,
fontStyle
);
}
break;
}
if (result) {
// Found the font!
break;
}
}
if (result) {
// Found the font!
break;
}
}
if (!result) {
result = android.graphics.Typeface.create("sans-serif" + getFontWeightSuffix(font.fontWeight), fontStyle);
}
if (!result) {
result = android.graphics.Typeface.create(
"sans-serif" + getFontWeightSuffix(font.fontWeight),
fontStyle
);
}
return result;
return result;
}
function getFontWeightSuffix(fontWeight: FontWeight): string {
switch (fontWeight) {
case FontWeight.THIN:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-thin" : "";
case FontWeight.EXTRA_LIGHT:
case FontWeight.LIGHT:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-light" : "";
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return "";
case FontWeight.MEDIUM:
case FontWeight.SEMI_BOLD:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-medium" : "";
case FontWeight.BOLD:
case "700":
case FontWeight.EXTRA_BOLD:
return "";
case FontWeight.BLACK:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-black" : "";
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);
}
switch (fontWeight) {
case FontWeight.THIN:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-thin" : "";
case FontWeight.EXTRA_LIGHT:
case FontWeight.LIGHT:
return android.os.Build.VERSION.SDK_INT >= 16 ? "-light" : "";
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return "";
case FontWeight.MEDIUM:
case FontWeight.SEMI_BOLD:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-medium" : "";
case FontWeight.BOLD:
case "700":
case FontWeight.EXTRA_BOLD:
return "";
case FontWeight.BLACK:
return android.os.Build.VERSION.SDK_INT >= 21 ? "-black" : "";
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);
}
}

View File

@@ -1,61 +1,77 @@
export class Font {
public static default: Font;
public static default: Font;
public fontFamily: string;
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public fontSize: number;
public fontFamily: string;
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public fontSize: number;
public isBold: boolean;
public isItalic: boolean;
public isBold: boolean;
public isItalic: boolean;
constructor(family: string, size: number, style: FontStyle, weight: FontWeight);
constructor(
family: string,
size: number,
style: FontStyle,
weight: FontWeight
);
public getAndroidTypeface(): any /* android.graphics.Typeface */;
public getUIFont(defaultFont: any /* UIFont */): any /* UIFont */;
public getAndroidTypeface(): any /* android.graphics.Typeface */;
public getUIFont(defaultFont: any /* UIFont */): any /* UIFont */;
public withFontFamily(family: string): Font;
public withFontStyle(style: string): Font;
public withFontWeight(weight: string): Font;
public withFontSize(size: number): Font;
public withFontFamily(family: string): Font;
public withFontStyle(style: string): Font;
public withFontWeight(weight: string): Font;
public withFontSize(size: number): Font;
public static equals(value1: Font, value2: Font): boolean;
public static equals(value1: Font, value2: Font): boolean;
}
export type FontStyle = "normal" | "italic";
export namespace FontStyle {
export const NORMAL: "normal";
export const ITALIC: "italic";
export function isValid(value: any): boolean;
export function parse(value: string): FontStyle;
export const NORMAL: "normal";
export const ITALIC: "italic";
export function isValid(value: any): boolean;
export function parse(value: string): FontStyle;
}
export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900";
export type FontWeight =
| "100"
| "200"
| "300"
| "normal"
| "400"
| "500"
| "600"
| "bold"
| "700"
| "800"
| "900";
export namespace FontWeight {
export const THIN: "100";
export const EXTRA_LIGHT: "200";
export const LIGHT: "300";
export const NORMAL: "normal";
export const MEDIUM: "500";
export const SEMI_BOLD: "600";
export const BOLD: "bold";
export const EXTRA_BOLD: "800";
export const BLACK: "900";
export function isValid(value: any): boolean;
export function parse(value: string): FontWeight;
export const THIN: "100";
export const EXTRA_LIGHT: "200";
export const LIGHT: "300";
export const NORMAL: "normal";
export const MEDIUM: "500";
export const SEMI_BOLD: "600";
export const BOLD: "bold";
export const EXTRA_BOLD: "800";
export const BLACK: "900";
export function isValid(value: any): boolean;
export function parse(value: string): FontWeight;
}
export interface ParsedFont {
fontStyle?: FontStyle;
fontVariant?: string;
fontWeight?: FontWeight,
lineHeight?: string,
fontSize?: string,
fontFamily?: string
fontStyle?: FontStyle;
fontVariant?: string;
fontWeight?: FontWeight;
lineHeight?: string;
fontSize?: string;
fontFamily?: string;
}
export function parseFont(fontValue: string): ParsedFont;
export module ios {
export function registerFont(fontFile: string);
export function registerFont(fontFile: string);
}

View File

@@ -1,4 +1,10 @@
import { Font as FontBase, parseFontFamily, genericFontFamilies, FontStyle, FontWeight } from "./font-common";
import {
Font as FontBase,
parseFontFamily,
genericFontFamilies,
FontStyle,
FontWeight,
} from "./font-common";
import { Trace } from "../../trace";
import { device } from "../../platform";
import * as fs from "../../file-system";
@@ -11,216 +17,266 @@ const DEFAULT_MONOSPACE = "Courier New";
const SUPPORT_FONT_WEIGHTS = parseFloat(device.osVersion) >= 10.0;
export class Font extends FontBase {
public static default = new Font(undefined, undefined, FontStyle.NORMAL, FontWeight.NORMAL);
public static default = new Font(
undefined,
undefined,
FontStyle.NORMAL,
FontWeight.NORMAL
);
private _uiFont: UIFont;
private _uiFont: UIFont;
constructor(family: string, size: number, style: FontStyle, weight: FontWeight) {
super(family, size, style, weight);
}
constructor(
family: string,
size: number,
style: FontStyle,
weight: FontWeight
) {
super(family, size, style, weight);
}
public withFontFamily(family: string): Font {
return new Font(family, this.fontSize, this.fontStyle, this.fontWeight);
}
public withFontFamily(family: string): Font {
return new Font(family, this.fontSize, this.fontStyle, this.fontWeight);
}
public withFontStyle(style: FontStyle): Font {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontStyle(style: FontStyle): Font {
return new Font(this.fontFamily, this.fontSize, style, this.fontWeight);
}
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
public withFontWeight(weight: FontWeight): Font {
return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight);
}
public withFontSize(size: number): Font {
return new Font(this.fontFamily, size, this.fontStyle, this.fontWeight);
}
public withFontSize(size: number): Font {
return new Font(this.fontFamily, size, this.fontStyle, this.fontWeight);
}
public getUIFont(defaultFont: UIFont): UIFont {
if (!this._uiFont) {
this._uiFont = createUIFont(this, defaultFont);
}
public getUIFont(defaultFont: UIFont): UIFont {
if (!this._uiFont) {
this._uiFont = createUIFont(this, defaultFont);
}
return this._uiFont;
}
return this._uiFont;
}
public getAndroidTypeface(): android.graphics.Typeface {
return undefined;
}
public getAndroidTypeface(): android.graphics.Typeface {
return undefined;
}
}
function getFontFamilyRespectingGenericFonts(fontFamily: string): string {
if (!fontFamily) {
return fontFamily;
}
if (!fontFamily) {
return fontFamily;
}
switch (fontFamily.toLowerCase()) {
case genericFontFamilies.serif:
return DEFAULT_SERIF;
switch (fontFamily.toLowerCase()) {
case genericFontFamilies.serif:
return DEFAULT_SERIF;
case genericFontFamilies.monospace:
return DEFAULT_MONOSPACE;
case genericFontFamilies.monospace:
return DEFAULT_MONOSPACE;
default:
return fontFamily;
}
default:
return fontFamily;
}
}
function shouldUseSystemFont(fontFamily: string) {
return !fontFamily ||
fontFamily === genericFontFamilies.sansSerif ||
fontFamily === genericFontFamilies.system;
return (
!fontFamily ||
fontFamily === genericFontFamilies.sansSerif ||
fontFamily === genericFontFamilies.system
);
}
function getNativeFontWeight(fontWeight: FontWeight): number {
switch (fontWeight) {
case FontWeight.THIN:
return UIFontWeightUltraLight;
case FontWeight.EXTRA_LIGHT:
return UIFontWeightThin;
case FontWeight.LIGHT:
return UIFontWeightLight;
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return UIFontWeightRegular;
case FontWeight.MEDIUM:
return UIFontWeightMedium;
case FontWeight.SEMI_BOLD:
return UIFontWeightSemibold;
case FontWeight.BOLD:
case "700":
return UIFontWeightBold;
case FontWeight.EXTRA_BOLD:
return UIFontWeightHeavy;
case FontWeight.BLACK:
return UIFontWeightBlack;
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);
}
switch (fontWeight) {
case FontWeight.THIN:
return UIFontWeightUltraLight;
case FontWeight.EXTRA_LIGHT:
return UIFontWeightThin;
case FontWeight.LIGHT:
return UIFontWeightLight;
case FontWeight.NORMAL:
case "400":
case undefined:
case null:
return UIFontWeightRegular;
case FontWeight.MEDIUM:
return UIFontWeightMedium;
case FontWeight.SEMI_BOLD:
return UIFontWeightSemibold;
case FontWeight.BOLD:
case "700":
return UIFontWeightBold;
case FontWeight.EXTRA_BOLD:
return UIFontWeightHeavy;
case FontWeight.BLACK:
return UIFontWeightBlack;
default:
throw new Error(`Invalid font weight: "${fontWeight}"`);
}
}
function getSystemFont(size: number, nativeWeight: number, italic: boolean, symbolicTraits: number): UIFont {
let result = UIFont.systemFontOfSizeWeight(size, nativeWeight);
if (italic) {
let descriptor = result.fontDescriptor.fontDescriptorWithSymbolicTraits(symbolicTraits);
result = UIFont.fontWithDescriptorSize(descriptor, size);
}
function getSystemFont(
size: number,
nativeWeight: number,
italic: boolean,
symbolicTraits: number
): UIFont {
let result = UIFont.systemFontOfSizeWeight(size, nativeWeight);
if (italic) {
let descriptor = result.fontDescriptor.fontDescriptorWithSymbolicTraits(
symbolicTraits
);
result = UIFont.fontWithDescriptorSize(descriptor, size);
}
return result;
return result;
}
function createUIFont(font: Font, defaultFont: UIFont): UIFont {
let result: UIFont;
const size = font.fontSize || defaultFont.pointSize;
const nativeWeight = getNativeFontWeight(font.fontWeight);
const fontFamilies = parseFontFamily(font.fontFamily);
let result: UIFont;
const size = font.fontSize || defaultFont.pointSize;
const nativeWeight = getNativeFontWeight(font.fontWeight);
const fontFamilies = parseFontFamily(font.fontFamily);
let symbolicTraits: number = 0;
if (font.isBold) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitBold;
}
if (font.isItalic) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitItalic;
}
let symbolicTraits: number = 0;
if (font.isBold) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitBold;
}
if (font.isItalic) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitItalic;
}
let fontDescriptorTraits = {
[UIFontSymbolicTrait]: symbolicTraits
};
let fontDescriptorTraits = {
[UIFontSymbolicTrait]: symbolicTraits,
};
// IOS versions below 10 will not return the correct font when UIFontWeightTrait is set
// In this case - rely on UIFontSymbolicTrait only
if (SUPPORT_FONT_WEIGHTS) {
fontDescriptorTraits[UIFontWeightTrait] = nativeWeight;
}
// IOS versions below 10 will not return the correct font when UIFontWeightTrait is set
// In this case - rely on UIFontSymbolicTrait only
if (SUPPORT_FONT_WEIGHTS) {
fontDescriptorTraits[UIFontWeightTrait] = nativeWeight;
}
for (let i = 0; i < fontFamilies.length; i++) {
const fontFamily = getFontFamilyRespectingGenericFonts(fontFamilies[i]);
for (let i = 0; i < fontFamilies.length; i++) {
const fontFamily = getFontFamilyRespectingGenericFonts(fontFamilies[i]);
if (shouldUseSystemFont(fontFamily)) {
result = getSystemFont(size, nativeWeight, font.isItalic, symbolicTraits);
break;
} else {
const fontAttributes = {
[UIFontDescriptorFamilyAttribute]: fontFamily,
[UIFontDescriptorTraitsAttribute]: fontDescriptorTraits
};
if (shouldUseSystemFont(fontFamily)) {
result = getSystemFont(
size,
nativeWeight,
font.isItalic,
symbolicTraits
);
break;
} else {
const fontAttributes = {
[UIFontDescriptorFamilyAttribute]: fontFamily,
[UIFontDescriptorTraitsAttribute]: fontDescriptorTraits,
};
let descriptor = UIFontDescriptor.fontDescriptorWithFontAttributes(<any>fontAttributes);
result = UIFont.fontWithDescriptorSize(descriptor, size);
let descriptor = UIFontDescriptor.fontDescriptorWithFontAttributes(
<any>fontAttributes
);
result = UIFont.fontWithDescriptorSize(descriptor, size);
let actualItalic = result.fontDescriptor.symbolicTraits & UIFontDescriptorSymbolicTraits.TraitItalic;
if (font.isItalic && !actualItalic && EMULATE_OBLIQUE) {
// The font we got is not actually italic so emulate that with a matrix
descriptor = descriptor.fontDescriptorWithMatrix(OBLIQUE_TRANSFORM);
result = UIFont.fontWithDescriptorSize(descriptor, size);
}
let actualItalic =
result.fontDescriptor.symbolicTraits &
UIFontDescriptorSymbolicTraits.TraitItalic;
if (font.isItalic && !actualItalic && EMULATE_OBLIQUE) {
// The font we got is not actually italic so emulate that with a matrix
descriptor = descriptor.fontDescriptorWithMatrix(
OBLIQUE_TRANSFORM
);
result = UIFont.fontWithDescriptorSize(descriptor, size);
}
// Check if the resolved font has the correct font-family
// If not - fallback to the next font-family
if (result.familyName === fontFamily) {
break;
} else {
result = null;
}
}
}
// Check if the resolved font has the correct font-family
// If not - fallback to the next font-family
if (result.familyName === fontFamily) {
break;
} else {
result = null;
}
}
}
// Couldn't resolve font - fallback to the system font
if (!result) {
result = getSystemFont(size, nativeWeight, font.isItalic, symbolicTraits);
}
// Couldn't resolve font - fallback to the system font
if (!result) {
result = getSystemFont(
size,
nativeWeight,
font.isItalic,
symbolicTraits
);
}
return result;
return result;
}
export module ios {
export function registerFont(fontFile: string) {
let filePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFile);
if (!fs.File.exists(filePath)) {
filePath = fs.path.join(fs.knownFolders.currentApp().path, fontFile);
}
const fontData = NSFileManager.defaultManager.contentsAtPath(filePath);
if (!fontData) {
throw new Error("Could not load font from: " + fontFile);
}
const provider = CGDataProviderCreateWithCFData(fontData);
const font = CGFontCreateWithDataProvider(provider);
export function registerFont(fontFile: string) {
let filePath = fs.path.join(
fs.knownFolders.currentApp().path,
"fonts",
fontFile
);
if (!fs.File.exists(filePath)) {
filePath = fs.path.join(
fs.knownFolders.currentApp().path,
fontFile
);
}
const fontData = NSFileManager.defaultManager.contentsAtPath(filePath);
if (!fontData) {
throw new Error("Could not load font from: " + fontFile);
}
const provider = CGDataProviderCreateWithCFData(fontData);
const font = CGFontCreateWithDataProvider(provider);
if (!font) {
throw new Error("Could not load font from: " + fontFile);
}
if (!font) {
throw new Error("Could not load font from: " + fontFile);
}
const error = new interop.Reference<NSError>();
if (!CTFontManagerRegisterGraphicsFont(font, error)) {
if (Trace.isEnabled()) {
Trace.write("Error occur while registering font: " + CFErrorCopyDescription(<NSError>error.value), Trace.categories.Error, Trace.messageType.error);
}
}
}
const error = new interop.Reference<NSError>();
if (!CTFontManagerRegisterGraphicsFont(font, error)) {
if (Trace.isEnabled()) {
Trace.write(
"Error occur while registering font: " +
CFErrorCopyDescription(<NSError>error.value),
Trace.categories.Error,
Trace.messageType.error
);
}
}
}
}
function registerFontsInFolder(fontsFolderPath) {
const fontsFolder = fs.Folder.fromPath(fontsFolderPath);
const fontsFolder = fs.Folder.fromPath(fontsFolderPath);
fontsFolder.eachEntity((fileEntity: fs.FileSystemEntity) => {
if (fs.Folder.exists(fs.path.join(fontsFolderPath, fileEntity.name))) {
return true;
}
if (fileEntity instanceof fs.File &&
((<fs.File>fileEntity).extension === ".ttf" || (<fs.File>fileEntity).extension === ".otf")) {
ios.registerFont(fileEntity.name);
}
fontsFolder.eachEntity((fileEntity: fs.FileSystemEntity) => {
if (fs.Folder.exists(fs.path.join(fontsFolderPath, fileEntity.name))) {
return true;
}
if (
fileEntity instanceof fs.File &&
((<fs.File>fileEntity).extension === ".ttf" ||
(<fs.File>fileEntity).extension === ".otf")
) {
ios.registerFont(fileEntity.name);
}
return true;
});
return true;
});
}
function registerCustomFonts() {
const appDir = fs.knownFolders.currentApp().path;
const fontsDir = fs.path.join(appDir, "fonts");
if (fs.Folder.exists(fontsDir)) {
registerFontsInFolder(fontsDir);
}
const appDir = fs.knownFolders.currentApp().path;
const fontsDir = fs.path.join(appDir, "fonts");
if (fs.Folder.exists(fontsDir)) {
registerFontsInFolder(fontsDir);
}
}
registerCustomFonts();

View File

@@ -3,15 +3,20 @@ import { Color } from "../../color";
import { LinearGradient as LinearGradientDefinition } from "../../css/parser";
export class LinearGradient {
public angle: number;
public colorStops: ColorStop[];
public angle: number;
public colorStops: ColorStop[];
public static parse(value: LinearGradientDefinition): LinearGradientDefinition;
public static parse(
value: LinearGradientDefinition
): LinearGradientDefinition;
public static equals(first: LinearGradientDefinition, second: LinearGradientDefinition): boolean;
public static equals(
first: LinearGradientDefinition,
second: LinearGradientDefinition
): boolean;
}
export interface ColorStop {
color: Color;
offset?: LengthPercentUnit;
color: Color;
offset?: LengthPercentUnit;
}

View File

@@ -4,58 +4,61 @@ import { ColorStop } from "./gradient";
import * as parser from "../../css/parser";
export class LinearGradient {
public angle: number;
public colorStops: ColorStop[];
public angle: number;
public colorStops: ColorStop[];
public static parse(value: parser.LinearGradient): LinearGradient {
const result = new LinearGradient();
result.angle = value.angle;
result.colorStops = value.colors.map(color => {
const offset = color.offset || null;
let offsetUnit: LengthPercentUnit;
public static parse(value: parser.LinearGradient): LinearGradient {
const result = new LinearGradient();
result.angle = value.angle;
result.colorStops = value.colors.map((color) => {
const offset = color.offset || null;
let offsetUnit: LengthPercentUnit;
if (offset && offset.unit === "%") {
offsetUnit = {
unit: "%",
value: offset.value
};
}
if (offset && offset.unit === "%") {
offsetUnit = {
unit: "%",
value: offset.value,
};
}
return {
color: new Color(color.argb),
offset: offsetUnit
};
});
return {
color: new Color(color.argb),
offset: offsetUnit,
};
});
return result;
}
return result;
}
public static equals(first: LinearGradient, second: LinearGradient): boolean {
if (!first && !second) {
return true;
} else if (!first || !second) {
return false;
}
public static equals(
first: LinearGradient,
second: LinearGradient
): boolean {
if (!first && !second) {
return true;
} else if (!first || !second) {
return false;
}
if (first.angle !== second.angle) {
return false;
}
if (first.angle !== second.angle) {
return false;
}
if (first.colorStops.length !== second.colorStops.length) {
return false;
}
if (first.colorStops.length !== second.colorStops.length) {
return false;
}
for (let i = 0; i < first.colorStops.length; i++) {
const firstStop = first.colorStops[i];
const secondStop = second.colorStops[i];
if (firstStop.offset !== secondStop.offset) {
return false;
}
if (!Color.equals(firstStop.color, secondStop.color)) {
return false;
}
}
for (let i = 0; i < first.colorStops.length; i++) {
const firstStop = first.colorStops[i];
const secondStop = second.colorStops[i];
if (firstStop.offset !== secondStop.offset) {
return false;
}
if (!Color.equals(firstStop.color, secondStop.color)) {
return false;
}
}
return true;
}
return true;
}
}

View File

@@ -1,41 +1,55 @@
import { TransformFunctionsInfo } from "../animation/animation";
import { Color } from "../../color";
import { CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from "../core/properties";
import {
CssProperty,
CssAnimationProperty,
ShorthandProperty,
InheritedCssProperty,
} from "../core/properties";
import { Style } from "../styling/style";
import { Font, FontStyle, FontWeight } from "./font";
import { Background } from "./background";
import { dip, px, percent } from "../core/view";
export type LengthDipUnit = { readonly unit: "dip", readonly value: dip };
export type LengthPxUnit = { readonly unit: "px", readonly value: px };
export type LengthPercentUnit = { readonly unit: "%", readonly value: percent };
export type LengthDipUnit = { readonly unit: "dip"; readonly value: dip };
export type LengthPxUnit = { readonly unit: "px"; readonly value: px };
export type LengthPercentUnit = { readonly unit: "%"; readonly value: percent };
export type Length = "auto" | dip | LengthDipUnit | LengthPxUnit;
export type PercentLength = "auto" | dip | LengthDipUnit | LengthPxUnit | LengthPercentUnit;
export type PercentLength =
| "auto"
| dip
| LengthDipUnit
| LengthPxUnit
| LengthPercentUnit;
export namespace Length {
export function parse(text: string): Length;
export function equals(a: Length, b: Length): boolean;
/**
* Converts Length unit to device pixels.
* @param length The Length to convert.
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
*/
export function toDevicePixels(length: Length, auto?: number): number;
export function convertToString(length: Length): string;
export function parse(text: string): Length;
export function equals(a: Length, b: Length): boolean;
/**
* Converts Length unit to device pixels.
* @param length The Length to convert.
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
*/
export function toDevicePixels(length: Length, auto?: number): number;
export function convertToString(length: Length): string;
}
export namespace PercentLength {
export function parse(text: string): PercentLength;
export function equals(a: PercentLength, b: PercentLength): boolean;
/**
* Converts PercentLength unit to device pixels.
* @param length The PercentLength to convert.
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
* @param parentAvailableWidth Value to use as base when converting percent unit. By default is Math.NaN.
*/
export function toDevicePixels(length: PercentLength, auto?: number, parentAvailableWidth?: px): number;
export function convertToString(length: PercentLength): string;
export function parse(text: string): PercentLength;
export function equals(a: PercentLength, b: PercentLength): boolean;
/**
* Converts PercentLength unit to device pixels.
* @param length The PercentLength to convert.
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
* @param parentAvailableWidth Value to use as base when converting percent unit. By default is Math.NaN.
*/
export function toDevicePixels(
length: PercentLength,
auto?: number,
parentAvailableWidth?: px
): number;
export function convertToString(length: PercentLength): string;
}
export const zeroLength: Length;
@@ -80,8 +94,14 @@ export const zIndexProperty: CssProperty<Style, number>;
export const visibilityProperty: CssProperty<Style, Visibility>;
export const opacityProperty: CssAnimationProperty<Style, number>;
export const minWidthProperty: CssProperty<Style, dip | LengthDipUnit | LengthPxUnit>;
export const minHeightProperty: CssProperty<Style, dip | LengthDipUnit | LengthPxUnit>;
export const minWidthProperty: CssProperty<
Style,
dip | LengthDipUnit | LengthPxUnit
>;
export const minHeightProperty: CssProperty<
Style,
dip | LengthDipUnit | LengthPxUnit
>;
export const widthProperty: CssAnimationProperty<Style, PercentLength>;
export const heightProperty: CssAnimationProperty<Style, PercentLength>;
export const lineHeightProperty: CssProperty<Style, number>;
@@ -97,7 +117,10 @@ export const paddingRightProperty: CssProperty<Style, Length>;
export const paddingTopProperty: CssProperty<Style, Length>;
export const paddingBottomProperty: CssProperty<Style, Length>;
export const horizontalAlignmentProperty: CssProperty<Style, HorizontalAlignment>;
export const horizontalAlignmentProperty: CssProperty<
Style,
HorizontalAlignment
>;
export const verticalAlignmentProperty: CssProperty<Style, VerticalAlignment>;
export const fontSizeProperty: InheritedCssProperty<Style, number>;

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +1,68 @@
//@private
import { ViewBase } from "../core/view-base";
import { SyntaxTree } from "../../css";
import { RuleSet, Node, SelectorCore, ChangeMap } from "../styling/css-selector";
import {
RuleSet,
Node,
SelectorCore,
ChangeMap,
} from "../styling/css-selector";
import { KeyframeAnimationInfo } from "../animation/keyframe-animation";
export class CssState {
/**
* Re-evaluate the selectors and apply any changes to the underlying view.
*/
public apply(): void;
/**
* Re-evaluate the selectors and apply any changes to the underlying view.
*/
public apply(): void;
/**
* Gets the static selectors that match the view and the dynamic selectors that may potentially match the view.
*/
public changeMap: ChangeMap<ViewBase>;
/**
* Gets the static selectors that match the view and the dynamic selectors that may potentially match the view.
*/
public changeMap: ChangeMap<ViewBase>;
/**
* Checks whether style scope and CSS state selectors are in sync.
*/
public isSelectorsLatestVersionApplied(): boolean
/**
* Checks whether style scope and CSS state selectors are in sync.
*/
public isSelectorsLatestVersionApplied(): boolean;
}
export class StyleScope {
public css: string;
public addCss(cssString: string, cssFileName?: string): void;
public addCssFile(cssFileName: string): void;
public changeCssFile(cssFileName: string): void;
public css: string;
public addCss(cssString: string, cssFileName?: string): void;
public addCssFile(cssFileName: string): void;
public changeCssFile(cssFileName: string): void;
public static createSelectorsFromCss(css: string, cssFileName: string, keyframes: Object): RuleSet[];
public static createSelectorsFromImports(tree: SyntaxTree, keyframes: Object): RuleSet[];
public ensureSelectors(): number;
public static createSelectorsFromCss(
css: string,
cssFileName: string,
keyframes: Object
): RuleSet[];
public static createSelectorsFromImports(
tree: SyntaxTree,
keyframes: Object
): RuleSet[];
public ensureSelectors(): number;
/**
* Increase the application CSS selector version.
*/
public _increaseApplicationCssSelectorVersion(): void;
public isApplicationCssSelectorsLatestVersionApplied(): boolean;
public isLocalCssSelectorsLatestVersionApplied(): boolean;
/**
* Increase the application CSS selector version.
*/
public _increaseApplicationCssSelectorVersion(): void;
public isApplicationCssSelectorsLatestVersionApplied(): boolean;
public isLocalCssSelectorsLatestVersionApplied(): boolean;
public applySelectors(view: ViewBase): void
public query(options: Node): SelectorCore[];
public applySelectors(view: ViewBase): void;
public query(options: Node): SelectorCore[];
public getKeyframeAnimationWithName(animationName: string): KeyframeAnimationInfo;
public getAnimations(ruleset: RuleSet): KeyframeAnimationInfo[];
public getKeyframeAnimationWithName(
animationName: string
): KeyframeAnimationInfo;
public getAnimations(ruleset: RuleSet): KeyframeAnimationInfo[];
}
export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean, importSource?: string): string;
export function resolveFileNameFromUrl(
url: string,
appDirectory: string,
fileExists: (string) => boolean,
importSource?: string
): string;
export function applyInlineStyle(view: ViewBase, style: string): void;

View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,235 +2,253 @@ import { Style as StyleDefinition } from ".";
import { Color } from "../../../color";
import { Font, FontStyle, FontWeight } from "../font";
import { Background } from "../background";
import { dip } from "../../core/view";
import { ViewBase } from "../../core/view-base";
import {
dip
} from "../../core/view";
import {
ViewBase
} from "../../core/view-base";
import {
Length, PercentLength,
HorizontalAlignment, VerticalAlignment, BackgroundRepeat, Visibility
Length,
PercentLength,
HorizontalAlignment,
VerticalAlignment,
BackgroundRepeat,
Visibility,
} from "../../styling/style-properties";
import {
LinearGradient
} from "../../styling/linear-gradient";
import { LinearGradient } from "../../styling/linear-gradient";
import { Observable } from "../../../data/observable";
import {
FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent,
Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf
FlexDirection,
FlexWrap,
JustifyContent,
AlignItems,
AlignContent,
Order,
FlexGrow,
FlexShrink,
FlexWrapBefore,
AlignSelf,
} from "../../layouts/flexbox-layout";
import { Trace } from "../../../trace";
import {
Trace
} from "../../../trace";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "../../text-base";
TextAlignment,
TextDecoration,
TextTransform,
WhiteSpace,
} from "../../text-base";
export interface CommonLayoutParams {
width: number;
height: number;
width: number;
height: number;
widthPercent: number;
heightPercent: number;
widthPercent: number;
heightPercent: number;
leftMargin: number;
topMargin: number;
rightMargin: number;
bottomMargin: number;
leftMargin: number;
topMargin: number;
rightMargin: number;
bottomMargin: number;
leftMarginPercent: number;
topMarginPercent: number;
rightMarginPercent: number;
bottomMarginPercent: number;
leftMarginPercent: number;
topMarginPercent: number;
rightMarginPercent: number;
bottomMarginPercent: number;
horizontalAlignment: HorizontalAlignment;
verticalAlignment: VerticalAlignment;
horizontalAlignment: HorizontalAlignment;
verticalAlignment: VerticalAlignment;
}
export class Style extends Observable implements StyleDefinition {
private unscopedCssVariables = new Map<string, string>();
private scopedCssVariables = new Map<string, string>();
private unscopedCssVariables = new Map<string, string>();
private scopedCssVariables = new Map<string, string>();
constructor(ownerView: ViewBase | WeakRef<ViewBase>) {
super();
constructor(ownerView: ViewBase | WeakRef<ViewBase>) {
super();
// HACK: Could not find better way for cross platform WeakRef type checking.
if (ownerView.constructor.toString().indexOf("[native code]") !== -1) {
this.viewRef = <WeakRef<ViewBase>>ownerView;
} else {
this.viewRef = new WeakRef(<ViewBase>ownerView);
}
}
// HACK: Could not find better way for cross platform WeakRef type checking.
if (ownerView.constructor.toString().indexOf("[native code]") !== -1) {
this.viewRef = <WeakRef<ViewBase>>ownerView;
} else {
this.viewRef = new WeakRef(<ViewBase>ownerView);
}
}
public setScopedCssVariable(varName: string, value: string): void {
this.scopedCssVariables.set(varName, value);
}
public setScopedCssVariable(varName: string, value: string): void {
this.scopedCssVariables.set(varName, value);
}
public setUnscopedCssVariable(varName: string, value: string): void {
this.unscopedCssVariables.set(varName, value);
}
public setUnscopedCssVariable(varName: string, value: string): void {
this.unscopedCssVariables.set(varName, value);
}
public getCssVariable(varName: string): string | null {
const view = this.view;
if (!view) {
return null;
}
public getCssVariable(varName: string): string | null {
const view = this.view;
if (!view) {
return null;
}
if (this.unscopedCssVariables.has(varName)) {
return this.unscopedCssVariables.get(varName);
}
if (this.unscopedCssVariables.has(varName)) {
return this.unscopedCssVariables.get(varName);
}
if (this.scopedCssVariables.has(varName)) {
return this.scopedCssVariables.get(varName);
}
if (this.scopedCssVariables.has(varName)) {
return this.scopedCssVariables.get(varName);
}
if (!view.parent || !view.parent.style) {
return null;
}
if (!view.parent || !view.parent.style) {
return null;
}
return view.parent.style.getCssVariable(varName);
}
return view.parent.style.getCssVariable(varName);
}
public resetScopedCssVariables() {
this.scopedCssVariables.clear();
}
public resetScopedCssVariables() {
this.scopedCssVariables.clear();
}
public resetUnscopedCssVariables() {
this.unscopedCssVariables.clear();
}
public resetUnscopedCssVariables() {
this.unscopedCssVariables.clear();
}
toString() {
const view = this.viewRef.get();
if (!view) {
Trace.write(`toString() of Style cannot execute correctly because ".viewRef" is cleared`, Trace.categories.Animation, Trace.messageType.warn);
toString() {
const view = this.viewRef.get();
if (!view) {
Trace.write(
`toString() of Style cannot execute correctly because ".viewRef" is cleared`,
Trace.categories.Animation,
Trace.messageType.warn
);
return "";
}
return "";
}
return `${view}.style`;
}
return `${view}.style`;
}
public fontInternal: Font;
public backgroundInternal: Background;
public fontInternal: Font;
public backgroundInternal: Background;
public rotate: number;
public rotateX: number;
public rotateY: number;
public perspective: number;
public rotate: number;
public rotateX: number;
public rotateY: number;
public perspective: number;
public scaleX: number;
public scaleY: number;
public translateX: dip;
public translateY: dip;
public scaleX: number;
public scaleY: number;
public translateX: dip;
public translateY: dip;
public clipPath: string;
public color: Color;
public tintColor: Color;
public placeholderColor: Color;
public clipPath: string;
public color: Color;
public tintColor: Color;
public placeholderColor: Color;
public background: string;
public backgroundColor: Color;
public backgroundImage: string | LinearGradient;
public backgroundRepeat: BackgroundRepeat;
public backgroundSize: string;
public backgroundPosition: string;
public background: string;
public backgroundColor: Color;
public backgroundImage: string | LinearGradient;
public backgroundRepeat: BackgroundRepeat;
public backgroundSize: string;
public backgroundPosition: string;
public borderColor: string | Color;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderWidth: string | Length;
public borderTopWidth: Length;
public borderRightWidth: Length;
public borderBottomWidth: Length;
public borderLeftWidth: Length;
public borderRadius: string | Length;
public borderTopLeftRadius: Length;
public borderTopRightRadius: Length;
public borderBottomRightRadius: Length;
public borderBottomLeftRadius: Length;
public borderColor: string | Color;
public borderTopColor: Color;
public borderRightColor: Color;
public borderBottomColor: Color;
public borderLeftColor: Color;
public borderWidth: string | Length;
public borderTopWidth: Length;
public borderRightWidth: Length;
public borderBottomWidth: Length;
public borderLeftWidth: Length;
public borderRadius: string | Length;
public borderTopLeftRadius: Length;
public borderTopRightRadius: Length;
public borderBottomRightRadius: Length;
public borderBottomLeftRadius: Length;
public fontSize: number;
public fontFamily: string;
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public font: string;
public fontSize: number;
public fontFamily: string;
public fontStyle: FontStyle;
public fontWeight: FontWeight;
public font: string;
public androidElevation: number;
public androidDynamicElevationOffset: number;
public zIndex: number;
public opacity: number;
public visibility: Visibility;
public androidElevation: number;
public androidDynamicElevationOffset: number;
public zIndex: number;
public opacity: number;
public visibility: Visibility;
public letterSpacing: number;
public lineHeight: number;
public textAlignment: TextAlignment;
public textDecoration: TextDecoration;
public textTransform: TextTransform;
public whiteSpace: WhiteSpace;
public letterSpacing: number;
public lineHeight: number;
public textAlignment: TextAlignment;
public textDecoration: TextDecoration;
public textTransform: TextTransform;
public whiteSpace: WhiteSpace;
public minWidth: Length;
public minHeight: Length;
public width: PercentLength;
public height: PercentLength;
public margin: string | PercentLength;
public marginLeft: PercentLength;
public marginTop: PercentLength;
public marginRight: PercentLength;
public marginBottom: PercentLength;
public padding: string | Length;
public paddingLeft: Length;
public paddingTop: Length;
public paddingRight: Length;
public paddingBottom: Length;
public horizontalAlignment: HorizontalAlignment;
public verticalAlignment: VerticalAlignment;
public minWidth: Length;
public minHeight: Length;
public width: PercentLength;
public height: PercentLength;
public margin: string | PercentLength;
public marginLeft: PercentLength;
public marginTop: PercentLength;
public marginRight: PercentLength;
public marginBottom: PercentLength;
public padding: string | Length;
public paddingLeft: Length;
public paddingTop: Length;
public paddingRight: Length;
public paddingBottom: Length;
public horizontalAlignment: HorizontalAlignment;
public verticalAlignment: VerticalAlignment;
// TabView-specific props
public tabTextFontSize: number;
public tabTextColor: Color;
public tabBackgroundColor: Color;
public selectedTabTextColor: Color;
public androidSelectedTabHighlightColor: Color;
// TabView-specific props
public tabTextFontSize: number;
public tabTextColor: Color;
public tabBackgroundColor: Color;
public selectedTabTextColor: Color;
public androidSelectedTabHighlightColor: Color;
// ListView-specific props
public separatorColor: Color;
// ListView-specific props
public separatorColor: Color;
//SegmentedBar-specific props
public selectedBackgroundColor: Color;
//SegmentedBar-specific props
public selectedBackgroundColor: Color;
// Page-specific props
public statusBarStyle: "light" | "dark";
public androidStatusBarBackground: Color;
// Page-specific props
public statusBarStyle: "light" | "dark";
public androidStatusBarBackground: Color;
// ActionBar-specific props
public androidContentInset: string | Length;
public androidContentInsetLeft: Length;
public androidContentInsetRight: Length;
// ActionBar-specific props
public androidContentInset: string | Length;
public androidContentInsetLeft: Length;
public androidContentInsetRight: Length;
//flexbox layout properties
public flexDirection: FlexDirection;
public flexWrap: FlexWrap;
public justifyContent: JustifyContent;
public alignItems: AlignItems;
public alignContent: AlignContent;
public order: Order;
public flexGrow: FlexGrow;
public flexShrink: FlexShrink;
public flexWrapBefore: FlexWrapBefore;
public alignSelf: AlignSelf;
//flexbox layout properties
public flexDirection: FlexDirection;
public flexWrap: FlexWrap;
public justifyContent: JustifyContent;
public alignItems: AlignItems;
public alignContent: AlignContent;
public order: Order;
public flexGrow: FlexGrow;
public flexShrink: FlexShrink;
public flexWrapBefore: FlexWrapBefore;
public alignSelf: AlignSelf;
public PropertyBag: { new(): { [property: string]: string }, prototype: { [property: string]: string } };
public PropertyBag: {
new (): { [property: string]: string };
prototype: { [property: string]: string };
};
public viewRef: WeakRef<ViewBase>;
public viewRef: WeakRef<ViewBase>;
public get view(): ViewBase {
if (this.viewRef) {
return this.viewRef.get();
}
public get view(): ViewBase {
if (this.viewRef) {
return this.viewRef.get();
}
return undefined;
}
return undefined;
}
}
Style.prototype.PropertyBag = class { [property: string]: string; };
Style.prototype.PropertyBag = class {
[property: string]: string;
};