diff --git a/azul-css-parser/src/css_parser.rs b/azul-css-parser/src/css_parser.rs index dfd4f20f7..9121005db 100644 --- a/azul-css-parser/src/css_parser.rs +++ b/azul-css-parser/src/css_parser.rs @@ -11,7 +11,7 @@ use azul_css::{ LayoutMaxHeight, LayoutMinHeight, LayoutHeight, LayoutMaxWidth, LayoutMinWidth, LayoutWidth, StyleBorderRadius, PixelValue, PercentageValue, FloatValue, ColorU, LayoutMargin, StyleLetterSpacing, StyleTextColor, StyleBackground, StyleBoxShadow, - GradientStopPre, RadialGradient, StyleBackgroundColor, + GradientStopPre, RadialGradient, StyleBackgroundColor, StyleBackgroundSize, DirectionCorner, StyleBorder, Direction, CssImageId, LinearGradient, BoxShadowPreDisplayItem, BorderStyle, LayoutPadding, StyleBorderSide, BorderRadius, PixelSize, @@ -63,6 +63,7 @@ pub fn parse_key_value_pair<'a>(key: CssPropertyType, value: &'a str) -> Result< match key { BorderRadius => Ok(parse_style_border_radius(value)?.into()), BackgroundColor => Ok(parse_style_background_color(value)?.into()), + BackgroundSize => Ok(parse_style_background_size(value)?.into()), TextColor => Ok(parse_style_text_color(value)?.into()), Background => Ok(parse_style_background(value)?.into()), FontSize => Ok(parse_style_font_size(value)?.into()), @@ -1624,6 +1625,8 @@ impl_display!{CssShapeParseError<'a>, { pub struct RectStyle { /// Background color of this rectangle pub background_color: Option, + /// Background size of this rectangle + pub background_size: Option, /// Shadow color pub box_shadow: Option, /// Gradient (location) + stops @@ -1780,36 +1783,40 @@ pub fn parse_style_font_family<'a>(input: &'a str) -> Result ( } )} -pub const CSS_PROPERTY_KEY_MAP: [(CssPropertyType, &'static str);51] = [ +pub const CSS_PROPERTY_KEY_MAP: [(CssPropertyType, &'static str);52] = [ (CssPropertyType::BorderRadius, "border-radius"), (CssPropertyType::BackgroundColor, "background-color"), + (CssPropertyType::BackgroundSize, "background-size"), (CssPropertyType::TextColor, "color"), (CssPropertyType::Background, "background"), (CssPropertyType::FontSize, "font-size"), @@ -261,6 +262,7 @@ pub fn get_css_key_map() -> BTreeMap<&'static str, CssPropertyType> { pub enum CssPropertyType { BorderRadius, BackgroundColor, + BackgroundSize, TextColor, Background, FontSize, @@ -364,6 +366,7 @@ impl CssPropertyType { match self { | BorderRadius | BackgroundColor + | BackgroundSize | TextColor | Background | TextAlign @@ -390,6 +393,7 @@ impl fmt::Display for CssPropertyType { pub enum CssProperty { BorderRadius(StyleBorderRadius), BackgroundColor(StyleBackgroundColor), + BackgroundSize(StyleBackgroundSize), TextColor(StyleTextColor), Border(StyleBorder), Background(StyleBackground), @@ -428,6 +432,7 @@ impl CssProperty { match &self { CssProperty::BorderRadius(_) => CssPropertyType::BorderRadius, CssProperty::BackgroundColor(_) => CssPropertyType::BackgroundColor, + CssProperty::BackgroundSize(_) => CssPropertyType::BackgroundSize, CssProperty::TextColor(_) => CssPropertyType::TextColor, CssProperty::Border(_) => CssPropertyType::Border, CssProperty::Background(_) => CssPropertyType::Background, @@ -473,6 +478,7 @@ impl_from!(StyleTextAlignmentHorz, CssProperty::TextAlign); impl_from!(StyleLineHeight, CssProperty::LineHeight); impl_from!(StyleLetterSpacing, CssProperty::LetterSpacing); impl_from!(StyleBackgroundColor, CssProperty::BackgroundColor); +impl_from!(StyleBackgroundSize, CssProperty::BackgroundSize); impl_from!(StyleTextColor, CssProperty::TextColor); impl_from!(StyleCursor, CssProperty::Cursor); @@ -618,6 +624,13 @@ impl Default for StyleBackgroundColor { } } +/// Represents a `background-size` attribute +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum StyleBackgroundSize { + Contain, + Cover +} + /// Represents a `color` attribute #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct StyleTextColor(pub ColorU); @@ -1336,6 +1349,8 @@ impl Default for StyleTextAlignmentVert { pub struct RectStyle { /// Background color of this rectangle pub background_color: Option, + /// Background size of this rectangle + pub background_size: Option, /// Shadow color pub box_shadow: Option, /// Gradient (location) + stops diff --git a/azul/src/display_list.rs b/azul/src/display_list.rs index 0a47edeb7..5000b5ecd 100644 --- a/azul/src/display_list.rs +++ b/azul/src/display_list.rs @@ -24,7 +24,7 @@ use azul_css::{ Css, StyleTextAlignmentHorz, LayoutPosition,CssProperty, LayoutOverflow, StyleFontSize, StyleBorderRadius, PixelValue, FloatValue, LayoutMargin, StyleTextColor, StyleBackground, StyleBoxShadow, StyleBackgroundColor, - StyleBorder, BoxShadowPreDisplayItem, LayoutPadding, SizeMetric, + StyleBackgroundSize, StyleBorder, BoxShadowPreDisplayItem, LayoutPadding, SizeMetric, BoxShadowClipMode, FontId, StyleTextAlignmentVert, RectStyle, RectLayout, ColorU as StyleColorU }; @@ -916,6 +916,7 @@ fn displaylist_handle_rect<'a,'b,'c,'d,'e,'f,'g, T: Layout>( &bounds, referenced_mutable_content.builder, bg, + rect.style.background_size, &referenced_mutable_content.app_resources); } @@ -1690,6 +1691,7 @@ fn push_background( bounds: &TypedRect, builder: &mut DisplayListBuilder, background: &StyleBackground, + background_size: Option, app_resources: &AppResources) { use azul_css::StyleBackground::*; @@ -1745,7 +1747,11 @@ fn push_background( let image_dimensions = app_resources.images.get(image_id).and_then(|i| Some(i.get_dimensions())) .unwrap_or((bounds.size.width, bounds.size.height)); // better than crashing... - let size = TypedSize2D::new(image_dimensions.0, image_dimensions.1); + let size = match background_size { + Some(bg_size) => calculate_background_size(bg_size, &info, &image_dimensions), + None => TypedSize2D::new(image_dimensions.0, image_dimensions.1) + }; + push_image(info, builder, app_resources, image_id, size); } }, @@ -1753,6 +1759,27 @@ fn push_background( } } +struct Ratio { + width: f32, + height: f32 +} + +fn calculate_background_size(bg_size: StyleBackgroundSize, info: &PrimitiveInfo, image_dimensions: &(f32, f32)) +-> TypedSize2D +{ + let original_ratios = Ratio { + width: info.rect.size.width / image_dimensions.0, + height: info.rect.size.height / image_dimensions.1 + }; + + let ratio = match bg_size { + StyleBackgroundSize::Contain => original_ratios.width.min(original_ratios.height), + StyleBackgroundSize::Cover => original_ratios.width.max(original_ratios.height) + }; + + TypedSize2D::new(image_dimensions.0 * ratio, image_dimensions.1 * ratio) +} + #[inline] fn push_image( info: &PrimitiveInfo, @@ -1933,6 +1960,7 @@ fn populate_css_properties( match property { BorderRadius(b) => { rect.style.border_radius = Some(*b); }, BackgroundColor(c) => { rect.style.background_color = Some(*c); }, + BackgroundSize(c) => { rect.style.background_size = Some(*c); }, TextColor(t) => { rect.style.font_color = Some(*t); }, Border(b) => { StyleBorder::merge(&mut rect.style.border, &b); }, Background(b) => { rect.style.background = Some(b.clone()); },