11namespace AngleSharp . Css . Parser
22{
33 using AngleSharp . Css . Values ;
4- using AngleSharp . Io ;
54 using AngleSharp . Text ;
65 using System ;
76 using System . Collections . Generic ;
@@ -227,30 +226,130 @@ static class ColorParser
227226
228227 private static Color ? ParseLab ( StringSource source )
229228 {
230- // lab(50% 40 59.5)
231- // lab(50 % 40 59.5 / 0.5)
229+ var l = ParseLabComponent ( source ) ;
230+ source . SkipSpacesAndComments ( ) ;
231+ var a = ParseLabComponent ( source ) ;
232+ source . SkipSpacesAndComments ( ) ;
233+ var b = ParseLabComponent ( source ) ;
234+ source . SkipSpacesAndComments ( ) ;
235+ var c = source . Current ;
236+ var alpha = new Nullable < Double > ( 1.0 ) ;
237+
238+ if ( l != null && a != null && b != null )
239+ {
240+ source . SkipCurrentAndSpaces ( ) ;
241+
242+ if ( c == Symbols . Solidus )
243+ {
244+ alpha = ParseAlpha ( source ) ;
245+ source . SkipSpacesAndComments ( ) ;
246+ c = source . Current ;
247+ source . SkipCurrentAndSpaces ( ) ;
248+ }
249+
250+ if ( c == Symbols . RoundBracketClose )
251+ {
252+ return Color . FromLab ( l . Value , a . Value , b . Value , alpha . Value ) ;
253+ }
254+ }
255+
232256 return null ;
233257 }
234258
235259 private static Color ? ParseLch ( StringSource source )
236260 {
237- // lch(52.2% 72.2 50)
238- // lch(52.2 % 72.2 50 / 0.5)
261+ var l = ParseLabComponent ( source ) ;
262+ source . SkipSpacesAndComments ( ) ;
263+ var c = ParseLabComponent ( source ) ;
264+ source . SkipSpacesAndComments ( ) ;
265+ var h = ParseAngle ( source ) ;
266+ source . SkipSpacesAndComments ( ) ;
267+ var chr = source . Current ;
268+ var a = new Nullable < Double > ( 1.0 ) ;
269+
270+ if ( l != null && c != null && h != null )
271+ {
272+ source . SkipCurrentAndSpaces ( ) ;
273+
274+ if ( chr == Symbols . Solidus )
275+ {
276+ a = ParseAlpha ( source ) ;
277+ source . SkipSpacesAndComments ( ) ;
278+ chr = source . Current ;
279+ source . SkipCurrentAndSpaces ( ) ;
280+ }
281+
282+ if ( chr == Symbols . RoundBracketClose )
283+ {
284+ return Color . FromLch ( l . Value , c . Value , h . Value , a . Value ) ;
285+ }
286+ }
287+
239288 return null ;
240289 }
241290
242291
243292 private static Color ? ParseOklab ( StringSource source )
244293 {
245- // oklab(59% 0.1 0.1)
246- // oklab(59 % 0.1 0.1 / 0.5)
294+ var l = ParseLabComponent ( source ) ;
295+ source . SkipSpacesAndComments ( ) ;
296+ var a = ParseLabComponent ( source ) ;
297+ source . SkipSpacesAndComments ( ) ;
298+ var b = ParseLabComponent ( source ) ;
299+ source . SkipSpacesAndComments ( ) ;
300+ var c = source . Current ;
301+ var alpha = new Nullable < Double > ( 1.0 ) ;
302+
303+ if ( l != null && a != null && b != null )
304+ {
305+ source . SkipCurrentAndSpaces ( ) ;
306+
307+ if ( c == Symbols . Solidus )
308+ {
309+ alpha = ParseAlpha ( source ) ;
310+ source . SkipSpacesAndComments ( ) ;
311+ c = source . Current ;
312+ source . SkipCurrentAndSpaces ( ) ;
313+ }
314+
315+ if ( c == Symbols . RoundBracketClose )
316+ {
317+ return Color . FromOklab ( l . Value , a . Value , b . Value , alpha . Value ) ;
318+ }
319+ }
320+
247321 return null ;
248322 }
249323
250324 private static Color ? ParseOklch ( StringSource source )
251325 {
252- // oklch(60% 0.15 50)
253- // oklch(60 % 0.15 50 / 0.5)
326+ var l = ParseLabComponent ( source ) ;
327+ source . SkipSpacesAndComments ( ) ;
328+ var c = ParseLabComponent ( source ) ;
329+ source . SkipSpacesAndComments ( ) ;
330+ var h = ParseAngle ( source ) ;
331+ source . SkipSpacesAndComments ( ) ;
332+ var chr = source . Current ;
333+ var a = new Nullable < Double > ( 1.0 ) ;
334+
335+ if ( l != null && c != null && h != null )
336+ {
337+ source . SkipCurrentAndSpaces ( ) ;
338+
339+ if ( chr == Symbols . Solidus )
340+ {
341+ a = ParseAlpha ( source ) ;
342+ source . SkipSpacesAndComments ( ) ;
343+ chr = source . Current ;
344+ source . SkipCurrentAndSpaces ( ) ;
345+ }
346+
347+ if ( chr == Symbols . RoundBracketClose )
348+ {
349+ return Color . FromOklch ( l . Value , c . Value , h . Value , a . Value ) ;
350+ }
351+ }
352+
254353 return null ;
255354 }
256355
@@ -285,6 +384,31 @@ static class ColorParser
285384 return null ;
286385 }
287386
387+ private static Double ? ParseLabComponent ( StringSource source )
388+ {
389+ var pos = source . Index ;
390+ var unit = source . ParseUnit ( ) ;
391+
392+ if ( unit == null )
393+ {
394+ source . BackTo ( pos ) ;
395+
396+ if ( source . IsIdentifier ( CssKeywords . None ) )
397+ {
398+ return 0 ;
399+ }
400+
401+ return null ;
402+ }
403+
404+ if ( ( unit . Dimension == String . Empty || unit . Dimension == "%" ) && Double . TryParse ( unit . Value , NumberStyles . Float , CultureInfo . InvariantCulture , out var value ) )
405+ {
406+ return value ;
407+ }
408+
409+ return null ;
410+ }
411+
288412 private static Byte ? ParseRgbOrNoneComponent ( StringSource source )
289413 {
290414 var pos = source . Index ;
@@ -309,17 +433,19 @@ static class ColorParser
309433 {
310434 var unit = source . ParseUnit ( ) ;
311435
312- if ( unit != null &&
313- Int32 . TryParse ( unit . Value , NumberStyles . Integer , CultureInfo . InvariantCulture , out var value ) )
436+ if ( unit == null )
314437 {
315- if ( unit . Dimension == "%" )
316- {
317- return ( Byte ) Math . Round ( ( 255.0 * value ) / 100.0 ) ;
318- }
319- else if ( unit . Dimension == String . Empty )
320- {
321- return ( Byte ) Math . Max ( Math . Min ( value , 255f ) , 0f ) ;
322- }
438+ return null ;
439+ }
440+
441+ if ( unit . Dimension == String . Empty && Int32 . TryParse ( unit . Value , NumberStyles . Integer , CultureInfo . InvariantCulture , out var num ) )
442+ {
443+ return ( Byte ) Math . Max ( Math . Min ( num , 255f ) , 0f ) ;
444+ }
445+
446+ if ( unit . Dimension == "%" && Double . TryParse ( unit . Value , NumberStyles . Float , CultureInfo . InvariantCulture , out var val ) )
447+ {
448+ return ( Byte ) Math . Round ( ( 255.0 * val ) / 100.0 ) ;
323449 }
324450
325451 return null ;
0 commit comments