mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-21 07:50:38 +08:00
fix(color): support web standard #rrggbbaa format
original pr credit to @farfromrefug https://github.com/NativeScript/NativeScript/pull/8519 BREAKING CHANGE Long standing inconsistency with color handling here. BEFORE: ``` // #aarrggbb const color = new Color('#ff00ff00'); Label { background-color: #ff00ff00; } ``` AFTER: ``` // #rrggbbaa const color = new Color('#00ff00ff'); Label { background-color: #00ff00ff; } ```
This commit is contained in:
@ -39,7 +39,7 @@ export var test_Argb_Color = function () {
|
|||||||
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
|
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
|
||||||
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
|
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
|
||||||
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
|
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
|
||||||
TKUnit.assertEqual(color.hex, '#64FF6464', 'Color.hex not properly parsed');
|
TKUnit.assertEqual(color.hex, '#FF646464', 'Color.hex not properly parsed');
|
||||||
TKUnit.assertEqual(color.argb, 0x64ff6464, 'Color.argb not properly parsed');
|
TKUnit.assertEqual(color.argb, 0x64ff6464, 'Color.argb not properly parsed');
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,6 +86,6 @@ export var test_rgba_Color_CSS = function () {
|
|||||||
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
|
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
|
||||||
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
|
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
|
||||||
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
|
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
|
||||||
TKUnit.assertEqual(color.hex, '#80FF6464', 'Color.hex not properly parsed');
|
TKUnit.assertEqual(color.hex, '#FF646480', 'Color.hex not properly parsed');
|
||||||
TKUnit.assertEqual(color.argb, 0x80ff6464, 'Color.argb not properly parsed');
|
TKUnit.assertEqual(color.argb, 0x80ff6464, 'Color.argb not properly parsed');
|
||||||
};
|
};
|
||||||
|
@ -181,7 +181,7 @@ var _testNativeFontSizeFromLocal = function (views: Array<View>) {
|
|||||||
helper.assertAreClose(actualResult, expectedFontSize, 'FontSizeFromLocal');
|
helper.assertAreClose(actualResult, expectedFontSize, 'FontSizeFromLocal');
|
||||||
};
|
};
|
||||||
|
|
||||||
var actualColorHex = '#ffff0000';
|
var actualColorHex = '#ff0000ff';
|
||||||
var expectedNormalizedColorHex = '#FF0000';
|
var expectedNormalizedColorHex = '#FF0000';
|
||||||
var _testLocalColorFromCss = function (views: Array<View>) {
|
var _testLocalColorFromCss = function (views: Array<View>) {
|
||||||
var button = <Button>views[0];
|
var button = <Button>views[0];
|
||||||
@ -209,7 +209,7 @@ var _testNativeColorFromLocal = function (views: Array<View>) {
|
|||||||
TKUnit.assert(actualResult === expectedNormalizedColorHex, 'Actual: ' + actualResult + '; Expected: ' + expectedNormalizedColorHex);
|
TKUnit.assert(actualResult === expectedNormalizedColorHex, 'Actual: ' + actualResult + '; Expected: ' + expectedNormalizedColorHex);
|
||||||
};
|
};
|
||||||
|
|
||||||
var actualBackgroundColorHex = '#FF00FF00';
|
var actualBackgroundColorHex = '#00FF00FF';
|
||||||
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
||||||
var _testLocalBackgroundColorFromCss = function (views: Array<View>) {
|
var _testLocalBackgroundColorFromCss = function (views: Array<View>) {
|
||||||
var button = <Button>views[0];
|
var button = <Button>views[0];
|
||||||
@ -268,7 +268,7 @@ export var test_StateHighlighted_also_fires_pressedState = function () {
|
|||||||
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
||||||
var view = <Button>views[0];
|
var view = <Button>views[0];
|
||||||
var page = <Page>views[1];
|
var page = <Page>views[1];
|
||||||
var expectedColor = '#FFFF0000';
|
var expectedColor = '#FF0000FF';
|
||||||
var expectedNormalizedColor = '#FF0000';
|
var expectedNormalizedColor = '#FF0000';
|
||||||
page.css = 'button:pressed { background-color: ' + expectedColor + '; }';
|
page.css = 'button:pressed { background-color: ' + expectedColor + '; }';
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ export var test_StateHighlighted_also_fires_activeState = function () {
|
|||||||
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
||||||
var view = <Button>views[0];
|
var view = <Button>views[0];
|
||||||
var page = <Page>views[1];
|
var page = <Page>views[1];
|
||||||
var expectedColor = '#FFFF0000';
|
var expectedColor = '#FF0000FF';
|
||||||
var expectedNormalizedColor = '#FF0000';
|
var expectedNormalizedColor = '#FF0000';
|
||||||
page.css = 'button:active { background-color: ' + expectedColor + '; }';
|
page.css = 'button:active { background-color: ' + expectedColor + '; }';
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ export var test_applying_disabled_visual_State_when_button_is_disable = function
|
|||||||
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
|
||||||
var view = <Button>views[0];
|
var view = <Button>views[0];
|
||||||
var page = <Page>views[1];
|
var page = <Page>views[1];
|
||||||
var expectedColor = '#FFFF0000';
|
var expectedColor = '#FF0000FF';
|
||||||
var expectedNormalizedColor = '#FF0000';
|
var expectedNormalizedColor = '#FF0000';
|
||||||
page.css = 'button:disabled { background-color: ' + expectedColor + '; }';
|
page.css = 'button:disabled { background-color: ' + expectedColor + '; }';
|
||||||
|
|
||||||
|
@ -295,8 +295,8 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
|
|||||||
const label = this.testView;
|
const label = this.testView;
|
||||||
|
|
||||||
const fontSize = 14;
|
const fontSize = 14;
|
||||||
const color = '#FFFF0000';
|
const color = '#FF0000FF';
|
||||||
const backgroundColor = '#FF00FF00';
|
const backgroundColor = '#00FF00FF';
|
||||||
const testCss = ['.title {background-color: ', backgroundColor, '; ', 'color: ', color, '; ', 'font-size: ', fontSize, ';}'].join('');
|
const testCss = ['.title {background-color: ', backgroundColor, '; ', 'color: ', color, '; ', 'font-size: ', fontSize, ';}'].join('');
|
||||||
|
|
||||||
// >> label-cssclass
|
// >> label-cssclass
|
||||||
@ -566,7 +566,7 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
|
|||||||
let view = this.testView;
|
let view = this.testView;
|
||||||
let page = this.testPage;
|
let page = this.testPage;
|
||||||
this.waitUntilTestElementIsLoaded();
|
this.waitUntilTestElementIsLoaded();
|
||||||
let expectedColor = '#FFFF0000';
|
let expectedColor = '#FF0000FF';
|
||||||
let expectedNormalizedColor = '#FF0000';
|
let expectedNormalizedColor = '#FF0000';
|
||||||
|
|
||||||
page.css = 'label:disabled { background-color: ' + expectedColor + '; }';
|
page.css = 'label:disabled { background-color: ' + expectedColor + '; }';
|
||||||
|
@ -324,7 +324,7 @@ export function test_cssShouldBeAppliedToAllNestedElements() {
|
|||||||
const stackLayout = new StackLayout();
|
const stackLayout = new StackLayout();
|
||||||
stackLayout.addChild(label);
|
stackLayout.addChild(label);
|
||||||
testPage.content = stackLayout;
|
testPage.content = stackLayout;
|
||||||
testPage.css = 'stackLayout {background-color: #FFFF0000;} label {background-color: #FF00FF00;}';
|
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #00FF00FF;}';
|
||||||
|
|
||||||
const pageFactory = function () {
|
const pageFactory = function () {
|
||||||
return testPage;
|
return testPage;
|
||||||
@ -346,7 +346,7 @@ export function test_cssShouldBeAppliedAfterChangeToAllNestedElements() {
|
|||||||
const stackLayout = new StackLayout();
|
const stackLayout = new StackLayout();
|
||||||
stackLayout.addChild(label);
|
stackLayout.addChild(label);
|
||||||
testPage.content = stackLayout;
|
testPage.content = stackLayout;
|
||||||
testPage.css = 'stackLayout {background-color: #FFFF0000;} label {background-color: #FF00FF00;}';
|
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #00FF00FF;}';
|
||||||
|
|
||||||
const pageFactory = function () {
|
const pageFactory = function () {
|
||||||
return testPage;
|
return testPage;
|
||||||
@ -357,7 +357,7 @@ export function test_cssShouldBeAppliedAfterChangeToAllNestedElements() {
|
|||||||
TKUnit.assertEqual(label.style.backgroundColor.hex, '#00FF00');
|
TKUnit.assertEqual(label.style.backgroundColor.hex, '#00FF00');
|
||||||
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#FF0000');
|
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#FF0000');
|
||||||
|
|
||||||
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #FFFF0000;}';
|
testPage.css = 'stackLayout {background-color: #0000FFFF;} label {background-color: #FF0000FF;}';
|
||||||
TKUnit.assertEqual(label.style.backgroundColor.hex, '#FF0000');
|
TKUnit.assertEqual(label.style.backgroundColor.hex, '#FF0000');
|
||||||
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#0000FF');
|
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#0000FF');
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
Label {
|
Label {
|
||||||
background-color: #ff00ff00;
|
background-color: #00ff00ff;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
Label {
|
Label {
|
||||||
background-color: #ff00ff00;
|
background-color: #00ff00ff;
|
||||||
}
|
}
|
||||||
|
@ -514,7 +514,7 @@ export var testNativeFontSizeFromLocal = function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var expectedColorHex = '#FFFF0000';
|
var expectedColorHex = '#FF0000FF';
|
||||||
var expectedNormalizedColorHex = '#FF0000';
|
var expectedNormalizedColorHex = '#FF0000';
|
||||||
export var testLocalColorFromCss = function () {
|
export var testLocalColorFromCss = function () {
|
||||||
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
|
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
|
||||||
@ -548,7 +548,7 @@ export var testNativeColorFromLocal = function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var expectedBackgroundColorHex = '#FF00FF00';
|
var expectedBackgroundColorHex = '#00FF00FF';
|
||||||
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
||||||
export var testLocalBackgroundColorFromCss = function () {
|
export var testLocalBackgroundColorFromCss = function () {
|
||||||
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
|
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
|
||||||
@ -695,7 +695,7 @@ export function test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedT
|
|||||||
|
|
||||||
export function test_set_placeholder_color() {
|
export function test_set_placeholder_color() {
|
||||||
const view = new TextField();
|
const view = new TextField();
|
||||||
const expectedColorHex = '#FFFF0000';
|
const expectedColorHex = '#FF0000FF';
|
||||||
const expectedNormalizedColorHex = '#FF0000';
|
const expectedNormalizedColorHex = '#FF0000';
|
||||||
helper.buildUIAndRunTest(view, function (views: Array<View>) {
|
helper.buildUIAndRunTest(view, function (views: Array<View>) {
|
||||||
view.hint = 'Some text for hint';
|
view.hint = 'Some text for hint';
|
||||||
@ -707,7 +707,7 @@ export function test_set_placeholder_color() {
|
|||||||
|
|
||||||
export function test_set_placeholder_color_when_hint_is_not_set() {
|
export function test_set_placeholder_color_when_hint_is_not_set() {
|
||||||
const view = new TextField();
|
const view = new TextField();
|
||||||
const expectedColorHex = '#FFFF0000';
|
const expectedColorHex = '#FF0000FF';
|
||||||
const expectedNormalizedColorHex = '#FF0000';
|
const expectedNormalizedColorHex = '#FF0000';
|
||||||
helper.buildUIAndRunTest(view, function (views: Array<View>) {
|
helper.buildUIAndRunTest(view, function (views: Array<View>) {
|
||||||
view.setInlineStyle('placeholder-color: ' + expectedColorHex + ';');
|
view.setInlineStyle('placeholder-color: ' + expectedColorHex + ';');
|
||||||
|
@ -270,11 +270,11 @@ export var testHintColoriOS = function () {
|
|||||||
|
|
||||||
actualValue = textViewTestsNative.getNativeColor(textView).hex;
|
actualValue = textViewTestsNative.getNativeColor(textView).hex;
|
||||||
|
|
||||||
TKUnit.assertEqual(actualValue, '#38FF0000', 'Expected hint color to be a subtle transparent red: #38FF0000');
|
TKUnit.assertEqual(actualValue, '#FF000038', 'Expected hint color to be a subtle transparent red: #FF000038');
|
||||||
|
|
||||||
textView.text = 'text';
|
textView.text = 'text';
|
||||||
|
|
||||||
expectedValue = '#FFFF0000'; // red
|
expectedValue = '#FF0000FF'; // red
|
||||||
expectedNormalizedValue = '#FF0000';
|
expectedNormalizedValue = '#FF0000';
|
||||||
actualValue = textViewTestsNative.getNativeColor(textView).hex;
|
actualValue = textViewTestsNative.getNativeColor(textView).hex;
|
||||||
TKUnit.assert(actualValue === expectedNormalizedValue, 'Actual: ' + actualValue + '; Expected: ' + expectedNormalizedValue);
|
TKUnit.assert(actualValue === expectedNormalizedValue, 'Actual: ' + actualValue + '; Expected: ' + expectedNormalizedValue);
|
||||||
@ -403,7 +403,7 @@ export var testLocalLineHeightFromCss = function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var expectedColorHex = '#FFFF0000';
|
var expectedColorHex = '#FF0000FF';
|
||||||
var expectedNormalizedColorHex = '#FF0000';
|
var expectedNormalizedColorHex = '#FF0000';
|
||||||
export var testLocalColorFromCss = function () {
|
export var testLocalColorFromCss = function () {
|
||||||
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {
|
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {
|
||||||
@ -437,7 +437,7 @@ export var testNativeColorFromLocal = function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var expectedBackgroundColorHex = '#FF00FF00';
|
var expectedBackgroundColorHex = '#00FF00FF';
|
||||||
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
var expectedNormalizedBackgroundColorHex = '#00FF00';
|
||||||
export var testLocalBackgroundColorFromCss = function () {
|
export var testLocalBackgroundColorFromCss = function () {
|
||||||
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {
|
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {
|
||||||
|
@ -39,7 +39,7 @@ describe('css', () => {
|
|||||||
describe('color', () => {
|
describe('color', () => {
|
||||||
test(parseColor, ' #369 ', { start: 0, end: 7, value: 0xff336699 });
|
test(parseColor, ' #369 ', { start: 0, end: 7, value: 0xff336699 });
|
||||||
test(parseColor, ' #456789 ', { start: 0, end: 10, value: 0xff456789 });
|
test(parseColor, ' #456789 ', { start: 0, end: 10, value: 0xff456789 });
|
||||||
test(parseColor, ' #85456789 ', { start: 0, end: 12, value: 0x85456789 });
|
test(parseColor, ' #45678985 ', { start: 0, end: 12, value: 0x45678985 });
|
||||||
test(parseColor, ' rgb(255, 8, 128) ', { start: 0, end: 18, value: 0xffff0880 });
|
test(parseColor, ' rgb(255, 8, 128) ', { start: 0, end: 18, value: 0xffff0880 });
|
||||||
test(parseColor, ' rgba(255, 8, 128, 0.5) ', { start: 0, end: 24, value: 0x80ff0880 });
|
test(parseColor, ' rgba(255, 8, 128, 0.5) ', { start: 0, end: 24, value: 0x80ff0880 });
|
||||||
test(parseColor, ' hsl(330.9, 100%, 51.6%) ', { start: 0, end: 25, value: 0xffff0880 });
|
test(parseColor, ' hsl(330.9, 100%, 51.6%) ', { start: 0, end: 25, value: 0xffff0880 });
|
||||||
|
@ -26,8 +26,10 @@ export class Color implements definition.Color {
|
|||||||
const argb = knownColors.getKnownColor(arg);
|
const argb = knownColors.getKnownColor(arg);
|
||||||
this._name = arg;
|
this._name = arg;
|
||||||
this._argb = argb;
|
this._argb = argb;
|
||||||
} else if (HEX_REGEX.test(arg)) {
|
} else if (arg[0].charAt(0) === SHARP && (arg.length === 4 || arg.length === 7 || arg.length === 9)) {
|
||||||
// The parameter is a "#AARRGGBB" formatted string
|
// we dont use the regexp as it is quite slow. Instead we expect it to be a valid hex format
|
||||||
|
// strange that it would not be. And if it is not a thrown error seems best
|
||||||
|
// The parameter is a "#RRGGBBAA" formatted string
|
||||||
const hex = this._normalizeHex(arg);
|
const hex = this._normalizeHex(arg);
|
||||||
this._argb = this._argbFromString(hex);
|
this._argb = this._argbFromString(hex);
|
||||||
} else {
|
} else {
|
||||||
@ -73,7 +75,7 @@ export class Color implements definition.Color {
|
|||||||
if (this.a === 0xff) {
|
if (this.a === 0xff) {
|
||||||
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
||||||
} else {
|
} else {
|
||||||
return ('#' + this._componentToHex(this.a) + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b) + this._componentToHex(this.a)).toUpperCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +106,11 @@ export class Color implements definition.Color {
|
|||||||
if (hex.length === 6) {
|
if (hex.length === 6) {
|
||||||
// add the alpha component since the provided string is RRGGBB
|
// add the alpha component since the provided string is RRGGBB
|
||||||
intVal = (intVal & 0x00ffffff) + 0xff000000;
|
intVal = (intVal & 0x00ffffff) + 0xff000000;
|
||||||
|
} else {
|
||||||
|
// the new format is #RRGGBBAA
|
||||||
|
// we need to shift the alpha value to 0x01000000 position
|
||||||
|
const a = (intVal / 0x00000001) & 0xff;
|
||||||
|
intVal = (intVal >>> 8) + (a & 0xff) * 0x01000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
return intVal;
|
return intVal;
|
||||||
@ -157,7 +164,8 @@ export class Color implements definition.Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _normalizeHex(hexStr: string): string {
|
private _normalizeHex(hexStr: string): string {
|
||||||
if (hexStr.charAt(0) === SHARP && hexStr.length === 4) {
|
// we expect this to already has a # as first char as it is supposed to be tested before
|
||||||
|
if (hexStr.length === 4) {
|
||||||
// Duplicate each char after the #, so "#123" becomes "#112233"
|
// Duplicate each char after the #, so "#123" becomes "#112233"
|
||||||
hexStr = hexStr.charAt(0) + hexStr.charAt(1) + hexStr.charAt(1) + hexStr.charAt(2) + hexStr.charAt(2) + hexStr.charAt(3) + hexStr.charAt(3);
|
hexStr = hexStr.charAt(0) + hexStr.charAt(1) + hexStr.charAt(1) + hexStr.charAt(2) + hexStr.charAt(2) + hexStr.charAt(3) + hexStr.charAt(3);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user