@@ -400,104 +400,16 @@ fn clamp_f32(val: f32) -> u8 {
400
400
#[ inline]
401
401
fn parse_color_function ( name : & str , arguments : & mut Parser ) -> Result < Color , ( ) > {
402
402
let is_rgb = match_ignore_ascii_case ! { name,
403
- "rgba" => true ,
404
- "rgb" => true ,
405
- "hsl" => false ,
406
- "hsla" => false ,
403
+ "rgb" | "rgba" => true ,
404
+ "hsl" | "hsla" => false ,
407
405
_ => return Err ( ( ) )
408
406
} ;
409
407
410
- let red: u8 ;
411
- let green: u8 ;
412
- let blue: u8 ;
413
- let mut uses_commas = false ;
414
- if is_rgb {
415
- // Either integers or percentages, but all the same type.
416
- // https://drafts.csswg.org/css-color/#rgb-functions
417
- match try!( arguments. next ( ) ) {
418
- Token :: Number ( NumericValue { value : v, .. } ) => {
419
- red = clamp_i32 ( v as i32 ) ;
420
- green = clamp_i32 ( match try!( arguments. next ( ) ) {
421
- Token :: Number ( NumericValue { value : v, .. } ) => v,
422
- Token :: Comma => {
423
- uses_commas = true ;
424
- try!( arguments. expect_number ( ) )
425
- }
426
- _ => return Err ( ( ) )
427
- } as i32 ) ;
428
- if uses_commas {
429
- try!( arguments. expect_comma ( ) ) ;
430
- }
431
- blue = clamp_i32 ( try!( arguments. expect_number ( ) ) as i32 ) ;
432
- }
433
- Token :: Percentage ( ref v) => {
434
- red = clamp_f32 ( v. unit_value ) ;
435
- green = clamp_f32 ( match try!( arguments. next ( ) ) {
436
- Token :: Percentage ( ref v) => v. unit_value ,
437
- Token :: Comma => {
438
- uses_commas = true ;
439
- try!( arguments. expect_percentage ( ) )
440
- }
441
- _ => return Err ( ( ) )
442
- } ) ;
443
- if uses_commas {
444
- try!( arguments. expect_comma ( ) ) ;
445
- }
446
- blue = clamp_f32 ( try!( arguments. expect_percentage ( ) ) ) ;
447
- }
448
- _ => return Err ( ( ) )
449
- } ;
408
+ let ( red, green, blue, uses_commas) = if is_rgb {
409
+ parse_rgb_components_rgb ( arguments) ?
450
410
} else {
451
- let hue_degrees = match try!( arguments. next ( ) ) {
452
- Token :: Number ( NumericValue { value : v, .. } ) => v,
453
- Token :: Dimension ( NumericValue { value : v, .. } , unit) => {
454
- match & * unit {
455
- "deg" => v,
456
- "grad" => v * 360. / 400. ,
457
- "rad" => v * 360. / ( 2. * PI as f32 ) ,
458
- "turn" => v * 360. ,
459
- _ => return Err ( ( ) )
460
- }
461
- }
462
- _ => return Err ( ( ) )
463
- } ;
464
- // Subtract an integer before rounding, to avoid some rounding errors:
465
- let hue_normalized_degrees = hue_degrees - 360. * ( hue_degrees / 360. ) . floor ( ) ;
466
- let hue = hue_normalized_degrees / 360. ;
467
- // Saturation and lightness are clamped to 0% ... 100%
468
- // https://drafts.csswg.org/css-color/#the-hsl-notation
469
- let saturation = match try!( arguments. next ( ) ) {
470
- Token :: Percentage ( ref v) => v. unit_value ,
471
- Token :: Comma => {
472
- uses_commas = true ;
473
- try!( arguments. expect_percentage ( ) )
474
- }
475
- _ => return Err ( ( ) )
476
- } . max ( 0. ) . min ( 1. ) ;
477
- if uses_commas {
478
- try!( arguments. expect_comma ( ) ) ;
479
- }
480
- let lightness = try!( arguments. expect_percentage ( ) ) . max ( 0. ) . min ( 1. ) ;
481
-
482
- // https://drafts.csswg.org/css-color/#hsl-color
483
- // except with h pre-multiplied by 3, to avoid some rounding errors.
484
- fn hue_to_rgb ( m1 : f32 , m2 : f32 , mut h3 : f32 ) -> f32 {
485
- if h3 < 0. { h3 += 3. }
486
- if h3 > 3. { h3 -= 3. }
487
-
488
- if h3 * 2. < 1. { m1 + ( m2 - m1) * h3 * 2. }
489
- else if h3 * 2. < 3. { m2 }
490
- else if h3 < 2. { m1 + ( m2 - m1) * ( 2. - h3) * 2. }
491
- else { m1 }
492
- }
493
- let m2 = if lightness <= 0.5 { lightness * ( saturation + 1. ) }
494
- else { lightness + saturation - lightness * saturation } ;
495
- let m1 = lightness * 2. - m2;
496
- let hue_times_3 = hue * 3. ;
497
- red = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3 + 1. ) ) ;
498
- green = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3) ) ;
499
- blue = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3 - 1. ) ) ;
500
- }
411
+ parse_rgb_components_hsl ( arguments) ?
412
+ } ;
501
413
502
414
let alpha = if !arguments. is_exhausted ( ) {
503
415
if uses_commas {
@@ -524,13 +436,114 @@ fn parse_color_function(name: &str, arguments: &mut Parser) -> Result<Color, ()>
524
436
255
525
437
} ;
526
438
527
- /*
528
- let alpha = if has_alpha {
529
- try!(arguments.expect_comma());
530
- clamp_f32(try!(arguments.expect_number()))
531
- } else {
532
- 255
533
- };*/
534
439
try!( arguments. expect_exhausted ( ) ) ;
535
440
rgba ( red, green, blue, alpha)
536
441
}
442
+
443
+
444
+ #[ inline]
445
+ fn parse_rgb_components_rgb ( arguments : & mut Parser ) -> Result < ( u8 , u8 , u8 , bool ) , ( ) > {
446
+ let red: u8 ;
447
+ let green: u8 ;
448
+ let blue: u8 ;
449
+ let mut uses_commas = false ;
450
+
451
+ // Either integers or percentages, but all the same type.
452
+ // https://drafts.csswg.org/css-color/#rgb-functions
453
+ match try!( arguments. next ( ) ) {
454
+ Token :: Number ( NumericValue { value : v, .. } ) => {
455
+ red = clamp_i32 ( v as i32 ) ;
456
+ green = clamp_i32 ( match try!( arguments. next ( ) ) {
457
+ Token :: Number ( NumericValue { value : v, .. } ) => v,
458
+ Token :: Comma => {
459
+ uses_commas = true ;
460
+ try!( arguments. expect_number ( ) )
461
+ }
462
+ _ => return Err ( ( ) )
463
+ } as i32 ) ;
464
+ if uses_commas {
465
+ try!( arguments. expect_comma ( ) ) ;
466
+ }
467
+ blue = clamp_i32 ( try!( arguments. expect_number ( ) ) as i32 ) ;
468
+ }
469
+ Token :: Percentage ( ref v) => {
470
+ red = clamp_f32 ( v. unit_value ) ;
471
+ green = clamp_f32 ( match try!( arguments. next ( ) ) {
472
+ Token :: Percentage ( ref v) => v. unit_value ,
473
+ Token :: Comma => {
474
+ uses_commas = true ;
475
+ try!( arguments. expect_percentage ( ) )
476
+ }
477
+ _ => return Err ( ( ) )
478
+ } ) ;
479
+ if uses_commas {
480
+ try!( arguments. expect_comma ( ) ) ;
481
+ }
482
+ blue = clamp_f32 ( try!( arguments. expect_percentage ( ) ) ) ;
483
+ }
484
+ _ => return Err ( ( ) )
485
+ } ;
486
+ return Ok ( ( red, green, blue, uses_commas) ) ;
487
+ }
488
+
489
+ #[ inline]
490
+ fn parse_rgb_components_hsl ( arguments : & mut Parser ) -> Result < ( u8 , u8 , u8 , bool ) , ( ) > {
491
+ let mut uses_commas = false ;
492
+ // Hue given as an angle
493
+ // https://drafts.csswg.org/css-values/#angles
494
+ let hue_degrees = match try!( arguments. next ( ) ) {
495
+ Token :: Number ( NumericValue { value : v, .. } ) => v,
496
+ Token :: Dimension ( NumericValue { value : v, .. } , unit) => {
497
+ match_ignore_ascii_case ! { & * unit,
498
+ "deg" => v,
499
+ "grad" => v * 360. / 400. ,
500
+ "rad" => v * 360. / ( 2. * PI as f32 ) ,
501
+ "turn" => v * 360. ,
502
+ _ => return Err ( ( ) )
503
+ }
504
+ }
505
+ _ => return Err ( ( ) )
506
+ } ;
507
+ // Subtract an integer before rounding, to avoid some rounding errors:
508
+ let hue_normalized_degrees = hue_degrees - 360. * ( hue_degrees / 360. ) . floor ( ) ;
509
+ let hue = hue_normalized_degrees / 360. ;
510
+
511
+ // Saturation and lightness are clamped to 0% ... 100%
512
+ // https://drafts.csswg.org/css-color/#the-hsl-notation
513
+ let saturation = match try!( arguments. next ( ) ) {
514
+ Token :: Percentage ( ref v) => v. unit_value ,
515
+ Token :: Comma => {
516
+ uses_commas = true ;
517
+ try!( arguments. expect_percentage ( ) )
518
+ }
519
+ _ => return Err ( ( ) )
520
+ } ;
521
+ let saturation = saturation. max ( 0. ) . min ( 1. ) ;
522
+
523
+ if uses_commas {
524
+ try!( arguments. expect_comma ( ) ) ;
525
+ }
526
+
527
+ let lightness = try!( arguments. expect_percentage ( ) ) ;
528
+ let lightness = lightness. max ( 0. ) . min ( 1. ) ;
529
+
530
+ // https://drafts.csswg.org/css-color/#hsl-color
531
+ // except with h pre-multiplied by 3, to avoid some rounding errors.
532
+ fn hue_to_rgb ( m1 : f32 , m2 : f32 , mut h3 : f32 ) -> f32 {
533
+ if h3 < 0. { h3 += 3. }
534
+ if h3 > 3. { h3 -= 3. }
535
+
536
+ if h3 * 2. < 1. { m1 + ( m2 - m1) * h3 * 2. }
537
+ else if h3 * 2. < 3. { m2 }
538
+ else if h3 < 2. { m1 + ( m2 - m1) * ( 2. - h3) * 2. }
539
+ else { m1 }
540
+ }
541
+ let m2 = if lightness <= 0.5 { lightness * ( saturation + 1. ) }
542
+ else { lightness + saturation - lightness * saturation } ;
543
+ let m1 = lightness * 2. - m2;
544
+ let hue_times_3 = hue * 3. ;
545
+ let red = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3 + 1. ) ) ;
546
+ let green = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3) ) ;
547
+ let blue = clamp_f32 ( hue_to_rgb ( m1, m2, hue_times_3 - 1. ) ) ;
548
+ return Ok ( ( red, green, blue, uses_commas) ) ;
549
+ }
0 commit comments