What do you think about that? Alternatively, I could parse these expressions from HtmlReadWriter, but I imagined they could be useful for other senders of Color fromString: as well. :-)
Best,
Christoph
=============== Summary ===============
Change Set: Color-fromString-css-function
Date: 20 May 2023
Author: Christoph Thiede
Adds support for basic CSS color functions to Color fromString:. This may be especially helpful for parsing HTML. While there are other color functions in CSS such as hsv(), lch(), oklab(), et al. for color models that we don't support, and CSS colors may be complex expressions, simple rgb() and argb() expressions are especially common.
=============== Diff ===============
Color class>>fromRGBAString: {other} · ct 5/19/2023 23:49
+ fromRGBAString: rgba
+ "Do not call this method directly, call Color>>#fromString: instead as it is more generic"
+
+ | alpha |
+ alpha := (Float readFrom:(rgba at: 4)) min: 1 max: 0.
+ ^ (self fromRGBString: rgba)
+ alpha: alpha
Color class>>fromString: {instance creation} · ct 5/20/2023 18:40 (changed)
fromString: aString
"for HTML color spec: #FFCCAA or white/black/red/other name, or an r,g,b triplet string"
"Color fromString: '#FFCCAA'.
Color fromString: 'white'.
Color fromString: 'orange'
Color fromString: '126,42,33' "
| aColorHex rgb|
aString isEmptyOrNil ifTrue: [ ^self white ].
aString first = $#
ifTrue: [ aColorHex := aString allButFirst ]
ifFalse: [ aColorHex := aString ].
"is the string a 6 digit hex number?"
((aColorHex size = 6 or: [aColorHex size = 8]) and: [
aColorHex allSatisfy: [ :each | '0123456789ABCDEFabcdef' includes: each ] ])
ifTrue: [^ self fromHTMLString: aColorHex ].
+ "is the string a CSS function?"
+ aString last = $) ifTrue: [
+ "While there are other color functions in CSS such as hsv(), lch(), oklab(), et al. for color models that we don't support, and CSS colors may be complex expressions, simple rgb() and argb() expressions are especially common."
+ (aString beginsWith: 'rgb(') ifTrue: [
+ rgb := ((aString allButLast allButFirst: 4) findTokens: $,) collect: #withBlanksTrimmed.
+ ^ self fromRGBString: rgb].
+ (aString beginsWith: 'rgba(') ifTrue: [
+ | rgba |
+ rgba := ((aString allButLast allButFirst: 5) findTokens: $,) collect: #withBlanksTrimmed.
+ ^ self fromRGBAString: rgba].
+ self flag: #forLater. "support hsl and hsla"
+ ^ self white].
+
"is the string in the form a,b,c ?"
rgb := aColorHex findTokens: $, .
rgb size = 3 ifTrue: [^ self fromRGBString: rgb].
"try to match aColorHex with known named colors, case insensitive"
^self perform: (ColorNames detect: [:colorSymbol | aColorHex sameAs: colorSymbol] ifNone: [ #white ])
ColorTest>>testFromString {tests} · ct 5/19/2023 23:48 (changed)
testFromString
self assert: ((Color fromString: '#FF8800') asHTMLColor sameAs: '#ff8800');
assert: ((Color fromString: 'FF8800') asHTMLColor sameAs: '#ff8800');
assert: ((Color fromString: '126,42,33') asHTMLColor sameAs: '#7E2A21');
assert: ((Color fromString: '00000000') asHTMLColor sameAs: '#00000000'); "html with alpha channel"
assert: ((Color fromString: '#8C500BAE') asHTMLColor sameAs: '#8C500BAE');
assert: ((Color fromString: 'white') asHTMLColor sameAs: '#ffffff');
assert: ((Color fromString: 'black') asHTMLColor sameAs: '#000000');
assert: ((Color fromString: nil) asHTMLColor sameAs: '#ffffff');
assert: ((Color fromString: 'inexistent color') asHTMLColor sameAs: '#ffffff'); "should return white"
assert: ((Color fromString: 'XXXXXX') asHTMLColor sameAs: '#ffffff') description: 'Color string should be alphanumeric';
assert: ((Color fromString: '000000000') asHTMLColor sameAs: '#ffffff') description: 'number string too long'.
self
assert: (Color fromString: 'DARKGRAY') = Color darkGray description: 'Color can be specified with a case insensitive color name';
- assert: (Color fromString: '#blue') = Color blue description: 'Color can be specified with a leading literal sharp'.
+ assert: (Color fromString: '#blue') = Color blue description: 'Color can be specified with a leading literal sharp'.
+
+ self
+ assert: (Color fromString: 'rgb(12,34,56)') = (Color r: 12 g: 34 b: 56 range: 255);
+ assert: (Color fromString: 'rgba(12,34,56,0.78)') = ((Color r: 12 g: 34 b: 56 range: 255) alpha: 0.78).
["Color-fromString-css-function.1.cs"]
---
Sent from Squeak Inbox Talk
["Color-fromString-css-function.1.cs"]