@@ -400,104 +400,16 @@ fn clamp_f32(val: f32) -> u8 {
400400#[ inline]
401401fn parse_color_function ( name : & str , arguments : & mut Parser ) -> Result < Color , ( ) > {
402402 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 ,
407405 _ => return Err ( ( ) )
408406 } ;
409407
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) ?
450410 } 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+ } ;
501413
502414 let alpha = if !arguments. is_exhausted ( ) {
503415 if uses_commas {
@@ -524,13 +436,114 @@ fn parse_color_function(name: &str, arguments: &mut Parser) -> Result<Color, ()>
524436 255
525437 } ;
526438
527- /*
528- let alpha = if has_alpha {
529- try!(arguments.expect_comma());
530- clamp_f32(try!(arguments.expect_number()))
531- } else {
532- 255
533- };*/
534439 try!( arguments. expect_exhausted ( ) ) ;
535440 rgba ( red, green, blue, alpha)
536441}
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