Skip to content

Commit ef33f49

Browse files
committed
fix(color): support web standard #rrggbbaa format
original pr credit to @farfromrefug #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; } ```
1 parent 1a791c0 commit ef33f49

File tree

10 files changed

+36
-28
lines changed

10 files changed

+36
-28
lines changed

apps/automated/src/color/color-tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export var test_Argb_Color = function () {
3939
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
4040
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
4141
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
42-
TKUnit.assertEqual(color.hex, '#64FF6464', 'Color.hex not properly parsed');
42+
TKUnit.assertEqual(color.hex, '#FF646464', 'Color.hex not properly parsed');
4343
TKUnit.assertEqual(color.argb, 0x64ff6464, 'Color.argb not properly parsed');
4444
};
4545

@@ -86,6 +86,6 @@ export var test_rgba_Color_CSS = function () {
8686
TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed');
8787
TKUnit.assertEqual(color.g, 100, 'Color.g not properly parsed');
8888
TKUnit.assertEqual(color.b, 100, 'Color.b not properly parsed');
89-
TKUnit.assertEqual(color.hex, '#80FF6464', 'Color.hex not properly parsed');
89+
TKUnit.assertEqual(color.hex, '#FF646480', 'Color.hex not properly parsed');
9090
TKUnit.assertEqual(color.argb, 0x80ff6464, 'Color.argb not properly parsed');
9191
};

apps/automated/src/ui/button/button-tests.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ var _testNativeFontSizeFromLocal = function (views: Array<View>) {
181181
helper.assertAreClose(actualResult, expectedFontSize, 'FontSizeFromLocal');
182182
};
183183

184-
var actualColorHex = '#ffff0000';
184+
var actualColorHex = '#ff0000ff';
185185
var expectedNormalizedColorHex = '#FF0000';
186186
var _testLocalColorFromCss = function (views: Array<View>) {
187187
var button = <Button>views[0];
@@ -209,7 +209,7 @@ var _testNativeColorFromLocal = function (views: Array<View>) {
209209
TKUnit.assert(actualResult === expectedNormalizedColorHex, 'Actual: ' + actualResult + '; Expected: ' + expectedNormalizedColorHex);
210210
};
211211

212-
var actualBackgroundColorHex = '#FF00FF00';
212+
var actualBackgroundColorHex = '#00FF00FF';
213213
var expectedNormalizedBackgroundColorHex = '#00FF00';
214214
var _testLocalBackgroundColorFromCss = function (views: Array<View>) {
215215
var button = <Button>views[0];
@@ -268,7 +268,7 @@ export var test_StateHighlighted_also_fires_pressedState = function () {
268268
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
269269
var view = <Button>views[0];
270270
var page = <Page>views[1];
271-
var expectedColor = '#FFFF0000';
271+
var expectedColor = '#FF0000FF';
272272
var expectedNormalizedColor = '#FF0000';
273273
page.css = 'button:pressed { background-color: ' + expectedColor + '; }';
274274

@@ -285,7 +285,7 @@ export var test_StateHighlighted_also_fires_activeState = function () {
285285
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
286286
var view = <Button>views[0];
287287
var page = <Page>views[1];
288-
var expectedColor = '#FFFF0000';
288+
var expectedColor = '#FF0000FF';
289289
var expectedNormalizedColor = '#FF0000';
290290
page.css = 'button:active { background-color: ' + expectedColor + '; }';
291291

@@ -302,7 +302,7 @@ export var test_applying_disabled_visual_State_when_button_is_disable = function
302302
helper.buildUIAndRunTest(_createButtonFunc(), function (views: Array<View>) {
303303
var view = <Button>views[0];
304304
var page = <Page>views[1];
305-
var expectedColor = '#FFFF0000';
305+
var expectedColor = '#FF0000FF';
306306
var expectedNormalizedColor = '#FF0000';
307307
page.css = 'button:disabled { background-color: ' + expectedColor + '; }';
308308

apps/automated/src/ui/label/label-tests.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
295295
const label = this.testView;
296296

297297
const fontSize = 14;
298-
const color = '#FFFF0000';
299-
const backgroundColor = '#FF00FF00';
298+
const color = '#FF0000FF';
299+
const backgroundColor = '#00FF00FF';
300300
const testCss = ['.title {background-color: ', backgroundColor, '; ', 'color: ', color, '; ', 'font-size: ', fontSize, ';}'].join('');
301301

302302
// >> label-cssclass
@@ -566,7 +566,7 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
566566
let view = this.testView;
567567
let page = this.testPage;
568568
this.waitUntilTestElementIsLoaded();
569-
let expectedColor = '#FFFF0000';
569+
let expectedColor = '#FF0000FF';
570570
let expectedNormalizedColor = '#FF0000';
571571

572572
page.css = 'label:disabled { background-color: ' + expectedColor + '; }';

apps/automated/src/ui/page/page-tests-common.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ export function test_cssShouldBeAppliedToAllNestedElements() {
324324
const stackLayout = new StackLayout();
325325
stackLayout.addChild(label);
326326
testPage.content = stackLayout;
327-
testPage.css = 'stackLayout {background-color: #FFFF0000;} label {background-color: #FF00FF00;}';
327+
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #00FF00FF;}';
328328

329329
const pageFactory = function () {
330330
return testPage;
@@ -346,7 +346,7 @@ export function test_cssShouldBeAppliedAfterChangeToAllNestedElements() {
346346
const stackLayout = new StackLayout();
347347
stackLayout.addChild(label);
348348
testPage.content = stackLayout;
349-
testPage.css = 'stackLayout {background-color: #FFFF0000;} label {background-color: #FF00FF00;}';
349+
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #00FF00FF;}';
350350

351351
const pageFactory = function () {
352352
return testPage;
@@ -357,7 +357,7 @@ export function test_cssShouldBeAppliedAfterChangeToAllNestedElements() {
357357
TKUnit.assertEqual(label.style.backgroundColor.hex, '#00FF00');
358358
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#FF0000');
359359

360-
testPage.css = 'stackLayout {background-color: #FF0000FF;} label {background-color: #FFFF0000;}';
360+
testPage.css = 'stackLayout {background-color: #0000FFFF;} label {background-color: #FF0000FF;}';
361361
TKUnit.assertEqual(label.style.backgroundColor.hex, '#FF0000');
362362
TKUnit.assertEqual(stackLayout.style.backgroundColor.hex, '#0000FF');
363363
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
Label {
2-
background-color: #ff00ff00;
2+
background-color: #00ff00ff;
33
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
Label {
2-
background-color: #ff00ff00;
2+
background-color: #00ff00ff;
33
}

apps/automated/src/ui/text-field/text-field-tests.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ export var testNativeFontSizeFromLocal = function () {
514514
});
515515
};
516516

517-
var expectedColorHex = '#FFFF0000';
517+
var expectedColorHex = '#FF0000FF';
518518
var expectedNormalizedColorHex = '#FF0000';
519519
export var testLocalColorFromCss = function () {
520520
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
@@ -548,7 +548,7 @@ export var testNativeColorFromLocal = function () {
548548
});
549549
};
550550

551-
var expectedBackgroundColorHex = '#FF00FF00';
551+
var expectedBackgroundColorHex = '#00FF00FF';
552552
var expectedNormalizedBackgroundColorHex = '#00FF00';
553553
export var testLocalBackgroundColorFromCss = function () {
554554
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
@@ -695,7 +695,7 @@ export function test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedT
695695

696696
export function test_set_placeholder_color() {
697697
const view = new TextField();
698-
const expectedColorHex = '#FFFF0000';
698+
const expectedColorHex = '#FF0000FF';
699699
const expectedNormalizedColorHex = '#FF0000';
700700
helper.buildUIAndRunTest(view, function (views: Array<View>) {
701701
view.hint = 'Some text for hint';
@@ -707,7 +707,7 @@ export function test_set_placeholder_color() {
707707

708708
export function test_set_placeholder_color_when_hint_is_not_set() {
709709
const view = new TextField();
710-
const expectedColorHex = '#FFFF0000';
710+
const expectedColorHex = '#FF0000FF';
711711
const expectedNormalizedColorHex = '#FF0000';
712712
helper.buildUIAndRunTest(view, function (views: Array<View>) {
713713
view.setInlineStyle('placeholder-color: ' + expectedColorHex + ';');

apps/automated/src/ui/text-view/text-view-tests.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,11 @@ export var testHintColoriOS = function () {
270270

271271
actualValue = textViewTestsNative.getNativeColor(textView).hex;
272272

273-
TKUnit.assertEqual(actualValue, '#38FF0000', 'Expected hint color to be a subtle transparent red: #38FF0000');
273+
TKUnit.assertEqual(actualValue, '#FF000038', 'Expected hint color to be a subtle transparent red: #FF000038');
274274

275275
textView.text = 'text';
276276

277-
expectedValue = '#FFFF0000'; // red
277+
expectedValue = '#FF0000FF'; // red
278278
expectedNormalizedValue = '#FF0000';
279279
actualValue = textViewTestsNative.getNativeColor(textView).hex;
280280
TKUnit.assert(actualValue === expectedNormalizedValue, 'Actual: ' + actualValue + '; Expected: ' + expectedNormalizedValue);
@@ -403,7 +403,7 @@ export var testLocalLineHeightFromCss = function () {
403403
});
404404
};
405405

406-
var expectedColorHex = '#FFFF0000';
406+
var expectedColorHex = '#FF0000FF';
407407
var expectedNormalizedColorHex = '#FF0000';
408408
export var testLocalColorFromCss = function () {
409409
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {
@@ -437,7 +437,7 @@ export var testNativeColorFromLocal = function () {
437437
});
438438
};
439439

440-
var expectedBackgroundColorHex = '#FF00FF00';
440+
var expectedBackgroundColorHex = '#00FF00FF';
441441
var expectedNormalizedBackgroundColorHex = '#00FF00';
442442
export var testLocalBackgroundColorFromCss = function () {
443443
helper.buildUIAndRunTest(_createTextViewFunc(), function (views: Array<viewModule.View>) {

packages/core/__tests__/css/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('css', () => {
3939
describe('color', () => {
4040
test(parseColor, ' #369 ', { start: 0, end: 7, value: 0xff336699 });
4141
test(parseColor, ' #456789 ', { start: 0, end: 10, value: 0xff456789 });
42-
test(parseColor, ' #85456789 ', { start: 0, end: 12, value: 0x85456789 });
42+
test(parseColor, ' #45678985 ', { start: 0, end: 12, value: 0x45678985 });
4343
test(parseColor, ' rgb(255, 8, 128) ', { start: 0, end: 18, value: 0xffff0880 });
4444
test(parseColor, ' rgba(255, 8, 128, 0.5) ', { start: 0, end: 24, value: 0x80ff0880 });
4545
test(parseColor, ' hsl(330.9, 100%, 51.6%) ', { start: 0, end: 25, value: 0xffff0880 });

packages/core/color/color-common.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ export class Color implements definition.Color {
2626
const argb = knownColors.getKnownColor(arg);
2727
this._name = arg;
2828
this._argb = argb;
29-
} else if (HEX_REGEX.test(arg)) {
30-
// The parameter is a "#AARRGGBB" formatted string
29+
} else if (arg[0].charAt(0) === SHARP && (arg.length === 4 || arg.length === 7 || arg.length === 9)) {
30+
// we dont use the regexp as it is quite slow. Instead we expect it to be a valid hex format
31+
// strange that it would not be. And if it is not a thrown error seems best
32+
// The parameter is a "#RRGGBBAA" formatted string
3133
const hex = this._normalizeHex(arg);
3234
this._argb = this._argbFromString(hex);
3335
} else {
@@ -73,7 +75,7 @@ export class Color implements definition.Color {
7375
if (this.a === 0xff) {
7476
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
7577
} else {
76-
return ('#' + this._componentToHex(this.a) + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
78+
return ('#' + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b) + this._componentToHex(this.a)).toUpperCase();
7779
}
7880
}
7981

@@ -104,6 +106,11 @@ export class Color implements definition.Color {
104106
if (hex.length === 6) {
105107
// add the alpha component since the provided string is RRGGBB
106108
intVal = (intVal & 0x00ffffff) + 0xff000000;
109+
} else {
110+
// the new format is #RRGGBBAA
111+
// we need to shift the alpha value to 0x01000000 position
112+
const a = (intVal / 0x00000001) & 0xff;
113+
intVal = (intVal >>> 8) + (a & 0xff) * 0x01000000;
107114
}
108115

109116
return intVal;
@@ -157,7 +164,8 @@ export class Color implements definition.Color {
157164
}
158165

159166
private _normalizeHex(hexStr: string): string {
160-
if (hexStr.charAt(0) === SHARP && hexStr.length === 4) {
167+
// we expect this to already has a # as first char as it is supposed to be tested before
168+
if (hexStr.length === 4) {
161169
// Duplicate each char after the #, so "#123" becomes "#112233"
162170
hexStr = hexStr.charAt(0) + hexStr.charAt(1) + hexStr.charAt(1) + hexStr.charAt(2) + hexStr.charAt(2) + hexStr.charAt(3) + hexStr.charAt(3);
163171
}

0 commit comments

Comments
 (0)