public static CssValue Font_Size_Used(ICssProperty Property) {/* Docs: https://www.w3.org/TR/css-fonts-3/#font-size-prop */ if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); double?v = (Property as CssProperty).Computed.Resolve(); if (!v.HasValue) { throw new CssException($"Unable to resolve absolute length for Used \"{Property.CssName}\" value."); } Contract.EndContractBlock(); double Size = v.Value; if (Size < 9.0)// The specifications say we shouldnt render a font less than 9px in size { Size = 9.0; } // Round the size up to the nearest whole pixel value Size = Math.Round(Size, MidpointRounding.AwayFromZero); return(CssValue.From(Size)); }
/// <summary> /// Properties that are defined in the CSS fonts module /// </summary> static IEnumerable <StyleDefinition> Create_Font_Property_Definitions() { return(new StyleDefinition[] { // SEE: https://www.w3.org/TR/CSS2/visudet.html#propdef-line-height new StyleDefinition(ECssPropertyID.LineHeight, true, EPropertyDirtFlags.Flow, CssValue.From(1.0), Percentage_Resolver: (Prop, Pct) => CssValue.From(Pct * Prop.Owner.Style.FontSize)), new StyleDefinition(ECssPropertyID.FontFamily, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.From(EGenericFontFamily.SansSerif), ECssValueTypes.STRING | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EGenericFontFamily>(), Resolvers: new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Font_Family_Used) ), new StyleDefinition(ECssPropertyID.FontWeight, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.From(EFontWeight.Normal), ECssValueTypes.KEYWORD | ECssValueTypes.INTEGER, Lookup.Get_Keywords <EFontWeight>(), Resolvers: new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Font_Weight_Computed) ), new StyleDefinition(ECssPropertyID.FontStyle, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.From(EFontStyle.Normal), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EFontStyle>()), //new StyleDefinition(ECssProperty.FontSize, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.From(12), new StyleDefinition(ECssPropertyID.FontSize, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.From(EFontSize.Medium), ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EFontSize>(), false, Percentage_Resolver: (Prop, Pct) => { if (!Prop.Owner.isRoot) { return CssValue.From(Pct * Prop.Owner.Style.FontSize); } else { // fallback to definition var def = StyleDefinitions[ECssPropertyID.FontSize]; //double r = def.Initial.Resolve() ?? throw new Exception("Failed to resolve default value from 'fontSize' definition"); var r = def.Initial.AsDecimal(); return CssValue.From(Pct * r); } }, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Font_Size_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Font_Size_Used) ), }); }
public static CssValue Containing_Block_Logical_Height(ICssProperty Property, double Percent) { if (!Property.Owner.Box.Containing_Box_Explicit_Height) { return(CssValue.Zero); } else { var resolved = Percent * CssCommon.Get_Logical_Height(Property.Owner.Style.WritingMode, Property.Owner.Box.Containing_Box); return(CssValue.From(resolved, ECssUnit.PX)); } }
public static CssValue Max_Height_Used(ICssProperty Property) {// Docs: https://www.w3.org/TR/css-sizing-3/#min-size-properties if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); CssValue Value = prop.Computed; if (Value.Type == ECssValueTypes.KEYWORD) { var keyword = Value.AsEnum <EBoxSize>(); switch (keyword) { case EBoxSize.Min_Content: { if (prop.Owner.Style.WritingMode != EWritingMode.Horizontal_TB) { return(prop.Definition.Initial); } return(CssValue.From(prop.Owner.Box.Min_Content.Height)); } case EBoxSize.Max_Content: { if (prop.Owner.Style.WritingMode != EWritingMode.Horizontal_TB) { return(prop.Definition.Initial); } return(CssValue.From(prop.Owner.Box.Max_Content.Height)); } case EBoxSize.Fit_Content: { // XXX: Implement this! throw new NotImplementedException(); } default: throw new NotImplementedException($"Keyword '{keyword}' is not implemented!"); } } return(Value); }
public static CssValue Position_Used(ICssProperty Property) { if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); CssValue Value = prop.Computed; if (!Value.IsDefinite) { return(CssValue.From(0)); } return(Value); }
public static CssValue Color_Computed(ICssProperty Property) { if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); CssValue Value = prop.Computed; if (Value.Type == ECssValueTypes.KEYWORD) { var keyword = Value.AsEnum <EColor>(); switch (keyword) { case EColor.CurrentColor: { /* This gets translated in the "Used" stage */ return(Value); } case EColor.Transparent: { /* The computed value of the keyword ‘transparent’ is the quadruplet of all zero numerical RGBA values, e.g. rgba(0,0,0,0). */ return(new CssValue(ECssValueTypes.COLOR, 0x0)); } default: { if (!Lookup.TryData(keyword, out EnumData outData)) { throw new CssPropertyException($"No meta-enum data found for keyword '{keyword}'"); } return(CssValue.From(new Color((int)outData.Data[1], (int)outData.Data[2], (int)outData.Data[3], (int)outData.Data[4]))); } } } return(Value); }
// private bool IsNegated = false; #endregion #region Constructors /// <summary> /// Creates a new 'boolean' type media feature /// </summary> /// <param name="name"></param> public MediaFeature(EMediaFeatureName Name) { Context = EMediaFeatureContext.Boolean; MediaDefinition def = MediaDefinition.Lookup(Name); if (def != null) { IsValid = true; /* if an allowed type is keywords and 'none' is an option then we match it against that keyword */ if (0 != (def.AllowedTypes & ECssValueTypes.KEYWORD) && def.KeywordWhitelist.Contains("none")) { Values = new CssValue[] { CssValue.From(Name), CssValue.None }; } else if (0 != (def.AllowedTypes & ECssValueTypes.INTEGER)) { Values = new CssValue[] { CssValue.From(Name), CssValue.From(0) }; } else if (0 != (def.AllowedTypes & ECssValueTypes.DIMENSION)) { Values = new CssValue[] { CssValue.From(Name), CssValue.From(0, ECssUnit.PX) }; } else if (0 != (def.AllowedTypes & ECssValueTypes.RESOLUTION)) { Values = new CssValue[] { CssValue.From(Name), CssValue.From(0, ECssUnit.DPPX) }; } } else { /* This isnt a supported feature, therefore it should always evaluate to false */ IsValid = false; } /* For sanity just catch the case where we dont have values to compare here */ if (Values.Length <= 0) { IsValid = false; } }
public static CssValue Opacity_Computed(ICssProperty Property) {/* Docs: https://www.w3.org/TR/css-color-3/#opacity */ if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); CssValue Value = prop.Computed; double n = Value.AsDecimal(); if (n < 0d) { return(CssValue.From(0d)); } else if (n > 1d) { return(CssValue.From(1d)); } return(Value); }
static IMediaCondition Consume_Media_Feature(DataConsumer <CssToken> Stream) {/* Docs: https://drafts.csswg.org/mediaqueries-4/#mq-syntax */ if (Stream is null) { throw new CssParserException(CssErrors.STREAM_IS_NULL); } /* Consume feature name */ if (ParserCommon.Starts_Boolean_Feature(Stream.AsSpan())) { /* Consume feature name */ IdentToken nameTok = Stream.Consume() as IdentToken; /* Resolve the name */ if (!Lookup.TryEnum(nameTok.Value, out EMediaFeatureName Name)) { throw new CssParserException(String.Format(CultureInfo.InvariantCulture, CssErrors.INVALID_MEDIA_TYPE, nameTok.Value), Stream); } return(new MediaFeature(Name)); } else if (ParserCommon.Starts_Discreet_Feature(Stream.AsSpan())) { /* Consume feature name */ IdentToken nameTok = Stream.Consume() as IdentToken; /* Resolve the name */ if (!Lookup.TryEnum(nameTok.Value, out EMediaFeatureName Name)) { throw new CssParserException(String.Format(CultureInfo.InvariantCulture, CssErrors.INVALID_MEDIA_TYPE, nameTok.Value), Stream); } /* Consume the value to match */ Consume_All_Whitespace(Stream); var value = Consume_MediaFeature_Value(Stream); return(new MediaFeature(new CssValue[] { CssValue.From(Name), value }, new EMediaOperator[] { EMediaOperator.EqualTo })); } else if (ParserCommon.Starts_Range_Feature(Stream.AsSpan())) { /* This is a range feature of some sort, it could be a short one or a long one */ /* Repeatedly consume CssValues, operator, and a single ident */ LinkedList <CssValue> Values = new LinkedList <CssValue>(); LinkedList <EMediaOperator> Ops = new LinkedList <EMediaOperator>(); bool firstToken = true; bool lastWasComparator = false; while (Stream.Next != CssToken.EOF) { Consume_All_Whitespace(Stream); if (Stream.Next.Type == ECssTokenType.Parenth_Close) { break; } else if (Stream.Next.Type == ECssTokenType.Ident) { if (!firstToken && !lastWasComparator) { throw new CssSyntaxErrorException(CssErrors.EXPECTING_COMPARATOR, Stream); } var nameTok = (IdentToken)Stream.Consume(); /* Resolve the name */ if (!Lookup.TryEnum(nameTok.Value, out EMediaFeatureName Name)) { throw new CssParserException(String.Format(CultureInfo.InvariantCulture, CssErrors.INVALID_MEDIA_TYPE, nameTok.Value), Stream); } var value = CssValue.From(Name); Values.AddLast(value); lastWasComparator = false; } else if (ParserCommon.Starts_MF_Ident_Or_Value(Stream.AsSpan())) { if (!firstToken && !lastWasComparator) { throw new CssSyntaxErrorException(CssErrors.EXPECTING_COMPARATOR, Stream); } CssValue value = Consume_MediaFeature_Value(Stream); Values.AddLast(value); lastWasComparator = false; } else if (ParserCommon.Is_Comparator(Stream.Next)) { if (lastWasComparator || firstToken) { throw new CssSyntaxErrorException(CssErrors.UNEXPECTED_TOKEN, Stream); } var comparatorTok = (ValuedTokenBase)Stream.Consume(); if (!Lookup.TryEnum(comparatorTok.Value, out EMediaOperator outComparator)) { throw new CssParserException(CssErrors.EXPECTING_COMPARATOR, Stream); } Ops.AddLast(outComparator); lastWasComparator = true; } firstToken = false; } return(new MediaFeature(Values.ToArray(), Ops.ToArray())); } return(null); }
public static CssValue Min_Width_Used(ICssProperty Property) {// Docs: https://www.w3.org/TR/css-sizing-3/#min-size-properties if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); CssValue Value = prop.Computed; if (Value.Type == ECssValueTypes.KEYWORD) { var keyword = Value.AsEnum <EBoxSize>(); switch (keyword) { case EBoxSize.Min_Content: { if (prop.Owner.Style.WritingMode != EWritingMode.Horizontal_TB) { return(prop.Definition.Initial); } return(CssValue.From(prop.Owner.Box.Min_Content.Width)); } case EBoxSize.Max_Content: { if (prop.Owner.Style.WritingMode != EWritingMode.Horizontal_TB) { return(prop.Definition.Initial); } return(CssValue.From(prop.Owner.Box.Max_Content.Width)); } case EBoxSize.Fit_Content: { // XXX: Implement this! throw new NotImplementedException(); } default: throw new NotImplementedException($"Keyword '{keyword}' is not implemented!"); } } else if (Value.Type == ECssValueTypes.AUTO) { /* * For min-width/min-height, specifies an automatic minimum size. * Unless otherwise defined by the relevant layout module, however, it resolves to a used value of 0. * For backwards-compatibility, the resolved value of this keyword is zero for boxes of all [CSS2] display types: block and inline boxes, inline blocks, and all the table layout boxes. * It also resolves to zero when no box is generated. */ switch (prop.Owner.Box.DisplayGroup) { case EBoxDisplayGroup.BLOCK: case EBoxDisplayGroup.INLINE: case EBoxDisplayGroup.INLINE_BLOCK: default: { return(CssValue.Zero); } } } return(Value); }
/// <summary> /// Properties that directly determine the size or position of an elements box /// </summary> static IEnumerable <StyleDefinition> Create_Block_Property_Definitions() { return(new StyleDefinition[] { new StyleDefinition(ECssPropertyID.Display, false, EPropertyDirtFlags.Box, CssValue.From(EDisplayMode.INLINE_BLOCK), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EDisplayMode>()), new StyleDefinition(ECssPropertyID.BoxSizing, false, EPropertyDirtFlags.Content_Area | EPropertyDirtFlags.Border_Area, CssValue.From(EBoxSizingMode.BorderBox), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBoxSizingMode>()), new StyleDefinition(ECssPropertyID.Positioning, false, EPropertyDirtFlags.Margin_Area, CssValue.From(EBoxPositioning.Relative), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBoxPositioning>()), new StyleDefinition(ECssPropertyID.ObjectPosition, false, EPropertyDirtFlags.Replaced_Area, CssValue.From(CssValue.Percent_50, CssValue.Percent_50), ECssValueTypes.COLLECTION | ECssValueTypes.KEYWORD | ECssValueTypes.INTEGER | ECssValueTypes.NUMBER | ECssValueTypes.PERCENT, Lookup.Get_Keywords <EPosition>(), false, Percentage_Resolver: (Prop, Pct) => CssValue.From(CssAlgorithms.Solve_Object_Axis_Position((float)Pct, Prop.Owner.Style.Box.Content.Width, Prop.Owner.Style.Box.Get_Replaced_Block_Size().Width)), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Position_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Position_Used)), // new StyleDefinition(ECssPropertyID.ObjectPositionX, false, EPropertyDirtFlags.Replaced_Area, CssValue.From_Percent(50.0), ECssValueTypes.POSITION, Percentage_Resolver: (Prop, Pct) => CssValue.From(CssAlgorithms.Solve_Object_Axis_Position((float)Pct, Prop.Owner.Style.Box.Content.Width, Prop.Owner.Style.Box.Get_Replaced_Block_Size().Width))), // new StyleDefinition(ECssPropertyID.ObjectPositionY, false, EPropertyDirtFlags.Replaced_Area, CssValue.From_Percent(50.0), ECssValueTypes.POSITION, Percentage_Resolver: (Prop, Pct) => CssValue.From(CssAlgorithms.Solve_Object_Axis_Position((float)Pct, Prop.Owner.Style.Box.Content.Height, Prop.Owner.Style.Box.Get_Replaced_Block_Size().Height))), new StyleDefinition(ECssPropertyID.Top, false, EPropertyDirtFlags.Margin_Area, CssValue.Auto, ECssValueTypes.AUTO | ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT, null, false, CssPercentageResolvers.Containing_Block_Logical_Height, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Definite_Or_Zero_Used)), new StyleDefinition(ECssPropertyID.Right, false, EPropertyDirtFlags.Margin_Area, CssValue.Auto, ECssValueTypes.AUTO | ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT, null, false, CssPercentageResolvers.Containing_Block_Logical_Width, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Definite_Or_Zero_Used)), new StyleDefinition(ECssPropertyID.Bottom, false, EPropertyDirtFlags.Margin_Area, CssValue.Auto, ECssValueTypes.AUTO | ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT, null, false, CssPercentageResolvers.Containing_Block_Logical_Height, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Definite_Or_Zero_Used)), new StyleDefinition(ECssPropertyID.Left, false, EPropertyDirtFlags.Margin_Area, CssValue.Auto, ECssValueTypes.AUTO | ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT, null, false, CssPercentageResolvers.Containing_Block_Logical_Width, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Definite_Or_Zero_Used)), new StyleDefinition(ECssPropertyID.Width, false, EPropertyDirtFlags.Content_Area, CssValue.Auto, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.AUTO | ECssValueTypes.INHERIT, null, false, CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.Height, false, EPropertyDirtFlags.Content_Area, CssValue.Auto, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.AUTO | ECssValueTypes.INHERIT, null, false, CssPercentageResolvers.Containing_Block_Logical_Height), new StyleDefinition(ECssPropertyID.MinWidth, false, EPropertyDirtFlags.Content_Area, CssValue.Auto, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.AUTO, Lookup.Get_Keywords <EBoxSize>(), false, CssPercentageResolvers.Containing_Block_Logical_Width, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Min_Width_Used)), new StyleDefinition(ECssPropertyID.MinHeight, false, EPropertyDirtFlags.Content_Area, CssValue.Auto, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.AUTO, Lookup.Get_Keywords <EBoxSize>(), false, CssPercentageResolvers.Containing_Block_Logical_Height, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Min_Height_Used)), new StyleDefinition(ECssPropertyID.MaxWidth, false, EPropertyDirtFlags.Content_Area, CssValue.None, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.NONE, Lookup.Get_Keywords <EBoxSize>(), false, CssPercentageResolvers.Containing_Block_Logical_Width, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Max_Width_Used)), new StyleDefinition(ECssPropertyID.MaxHeight, false, EPropertyDirtFlags.Content_Area, CssValue.None, ECssValueTypes.DIMENSION | ECssValueTypes.PERCENT | ECssValueTypes.NONE, Lookup.Get_Keywords <EBoxSize>(), false, CssPercentageResolvers.Containing_Block_Logical_Height, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Max_Height_Used)), // Padding percentages are all calculated against the containing block's width so it is possible to create elements which conform to an aspect ratio new StyleDefinition(ECssPropertyID.PaddingTop, false, EPropertyDirtFlags.Padding_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.PaddingRight, false, EPropertyDirtFlags.Padding_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.PaddingBottom, false, EPropertyDirtFlags.Padding_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.PaddingLeft, false, EPropertyDirtFlags.Padding_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.BorderTopWidth, false, EPropertyDirtFlags.Border_Area, CssValue.From(EBorderSize.Medium), ECssValueTypes.DIMENSION | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderSize>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Border_Width_Used)), new StyleDefinition(ECssPropertyID.BorderRightWidth, false, EPropertyDirtFlags.Border_Area, CssValue.From(EBorderSize.Medium), ECssValueTypes.DIMENSION | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderSize>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Border_Width_Used)), new StyleDefinition(ECssPropertyID.BorderBottomWidth, false, EPropertyDirtFlags.Border_Area, CssValue.From(EBorderSize.Medium), ECssValueTypes.DIMENSION | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderSize>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Border_Width_Used)), new StyleDefinition(ECssPropertyID.BorderLeftWidth, false, EPropertyDirtFlags.Border_Area, CssValue.From(EBorderSize.Medium), ECssValueTypes.DIMENSION | ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderSize>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Border_Width_Used)), // Margin percentages are all calculated against the containing block's width so it is possible to create elements which conform to an aspect ratio new StyleDefinition(ECssPropertyID.MarginTop, false, EPropertyDirtFlags.Margin_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.AUTO | ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Keywords: null, IsPrivate: false, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.MarginRight, false, EPropertyDirtFlags.Margin_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.AUTO | ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Keywords: null, IsPrivate: false, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.MarginBottom, false, EPropertyDirtFlags.Margin_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.AUTO | ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Keywords: null, IsPrivate: false, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width), new StyleDefinition(ECssPropertyID.MarginLeft, false, EPropertyDirtFlags.Margin_Area, CssValue.Zero, AllowedTypes: ECssValueTypes.AUTO | ECssValueTypes.PERCENT | ECssValueTypes.DIMENSION, Keywords: null, IsPrivate: false, Percentage_Resolver: CssPercentageResolvers.Containing_Block_Logical_Width) }); }
/// <summary> /// Properties that affect the sizing of sub elements /// </summary> static IEnumerable <StyleDefinition> Create_Sizing_Property_Definitions() { return(new StyleDefinition[] { // The ‘object-fit’ property specifies how the contents of a replaced element should be fitted to the box established by its used height and width. new StyleDefinition(ECssPropertyID.ObjectFit, false, EPropertyDirtFlags.Replaced_Area, CssValue.From(EObjectFit.Fill), ECssValueTypes.KEYWORD) }); }
/// <summary> /// Properties that affect the way elements position their sub elements /// </summary> static IEnumerable <StyleDefinition> Create_Layout_Property_Definitions() { return(new StyleDefinition[] { new StyleDefinition(ECssPropertyID.Direction, true, EPropertyDirtFlags.Flow, CssValue.From(EDirection.LTR), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EDirection>()), new StyleDefinition(ECssPropertyID.WritingMode, true, EPropertyDirtFlags.Flow, CssValue.From(EWritingMode.Horizontal_TB), 0x0, Lookup.Get_Keywords <EWritingMode>()), new StyleDefinition(ECssPropertyID.TextAlign, true, EPropertyDirtFlags.Flow, CssValue.From(ETextAlign.Start), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <ETextAlign>()) }); }
/// <summary> /// Properties that affect the way something is rendered /// </summary> static IEnumerable <StyleDefinition> Create_Rendering_Property_Definitions() { return(new StyleDefinition[] { new StyleDefinition(ECssPropertyID.ScrollBehavior, false, EPropertyDirtFlags.Visual, CssValue.From(EScrollBehavior.Auto), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EScrollBehavior>()), new StyleDefinition(ECssPropertyID.OverflowX, false, EPropertyDirtFlags.Visual, CssValue.From(EOverflowMode.Visible), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EOverflowMode>()), new StyleDefinition(ECssPropertyID.OverflowY, false, EPropertyDirtFlags.Visual, CssValue.From(EOverflowMode.Visible), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EOverflowMode>()), new StyleDefinition(ECssPropertyID.Color, true, EPropertyDirtFlags.Visual, CssValue.From(EColor.Black), ECssValueTypes.KEYWORD | ECssValueTypes.COLOR | ECssValueTypes.INHERIT, Lookup.Get_Keywords <EColor>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Specified, CssPropertyResolver.Color_Specified), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Color_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Color_Used)), new StyleDefinition(ECssPropertyID.Opacity, false, EPropertyDirtFlags.Visual, CssValue.From(1.0), ECssValueTypes.NUMBER | ECssValueTypes.INTEGER, null, false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Opacity_Computed)), new StyleDefinition(ECssPropertyID.BorderTopColor, false, EPropertyDirtFlags.Visual, CssValue.From(EColor.CurrentColor), ECssValueTypes.KEYWORD | ECssValueTypes.COLOR | ECssValueTypes.INHERIT, Lookup.Get_Keywords <EColor>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Specified, CssPropertyResolver.Color_Specified), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Color_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Color_Used)), new StyleDefinition(ECssPropertyID.BorderRightColor, false, EPropertyDirtFlags.Visual, CssValue.From(EColor.CurrentColor), ECssValueTypes.KEYWORD | ECssValueTypes.COLOR | ECssValueTypes.INHERIT, Lookup.Get_Keywords <EColor>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Specified, CssPropertyResolver.Color_Specified), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Color_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Color_Used)), new StyleDefinition(ECssPropertyID.BorderBottomColor, false, EPropertyDirtFlags.Visual, CssValue.From(EColor.CurrentColor), ECssValueTypes.KEYWORD | ECssValueTypes.COLOR | ECssValueTypes.INHERIT, Lookup.Get_Keywords <EColor>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Specified, CssPropertyResolver.Color_Specified), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Color_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Color_Used)), new StyleDefinition(ECssPropertyID.BorderLeftColor, false, EPropertyDirtFlags.Visual, CssValue.From(EColor.CurrentColor), ECssValueTypes.KEYWORD | ECssValueTypes.COLOR | ECssValueTypes.INHERIT, Lookup.Get_Keywords <EColor>(), false, null, new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Specified, CssPropertyResolver.Color_Specified), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Computed, CssPropertyResolver.Color_Computed), new Tuple <EPropertyStage, PropertyResolverFunc>(EPropertyStage.Used, CssPropertyResolver.Color_Used)), new StyleDefinition(ECssPropertyID.BorderTopStyle, false, EPropertyDirtFlags.Visual | EPropertyDirtFlags.Border_Area, CssValue.From(EBorderStyle.None), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderStyle>()), new StyleDefinition(ECssPropertyID.BorderRightStyle, false, EPropertyDirtFlags.Visual | EPropertyDirtFlags.Border_Area, CssValue.From(EBorderStyle.None), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderStyle>()), new StyleDefinition(ECssPropertyID.BorderBottomStyle, false, EPropertyDirtFlags.Visual | EPropertyDirtFlags.Border_Area, CssValue.From(EBorderStyle.None), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderStyle>()), new StyleDefinition(ECssPropertyID.BorderLeftStyle, false, EPropertyDirtFlags.Visual | EPropertyDirtFlags.Border_Area, CssValue.From(EBorderStyle.None), ECssValueTypes.KEYWORD, Lookup.Get_Keywords <EBorderStyle>()), // Was concerned about using CssValue.None as the initial value but thats what the specs say // SEE: https://www.w3.org/TR/css-transforms-1/#transform-property // The transform property is completely visual and does not change an elements box new StyleDefinition(ECssPropertyID.Transform, false, EPropertyDirtFlags.Visual, CssValue.None) }); }
/// <summary> /// Properties that can ONLY be set by the CssUI system /// </summary> static IEnumerable <StyleDefinition> Create_System_Property_Definitions() { return(new StyleDefinition[] { new StyleDefinition(ECssPropertyID.DpiX, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.Null, ECssValueTypes.NUMBER, null, false, (E, Pct) => CssValue.From(Pct * 72.0)), new StyleDefinition(ECssPropertyID.DpiY, true, EPropertyDirtFlags.Text | EPropertyDirtFlags.Flow, CssValue.Null, ECssValueTypes.NUMBER, null, false, (E, Pct) => CssValue.From(Pct * 72.0)), }); }
public static CssValue Font_Weight_Computed(ICssProperty Property) {/* Docs: https://drafts.csswg.org/css-fonts-4/#valdef-font-weight-bolder */ if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); // handle font-weight related keywords // This function wouldnt even be called if the value werent a keyword var keyword = (Property as CssProperty).Specified.AsEnum <EFontWeight>(); int Weight = 400; switch (keyword) { case EFontWeight.Normal: Weight = 400; break; case EFontWeight.Bold: Weight = 700; break; case EFontWeight.Bolder: { /* Docs: https://drafts.csswg.org/css-fonts-4/#relative-weights */ CssValue inherited = Property.Find_Inherited_Value(); int w = inherited.AsInteger(); if (w < 100) { Weight = 400; } else if (w >= 100 && w < 350) { Weight = 400; } else if (w >= 350 && w < 550) { Weight = 700; } else if (w >= 550 && w < 750) { Weight = 900; } else if (w >= 750 && w < 900) { Weight = 900; } else { Weight = 900; } } break; case EFontWeight.Lighter: { /* Docs: https://drafts.csswg.org/css-fonts-4/#relative-weights */ CssValue inherited = Property.Find_Inherited_Value(); int w = inherited.AsInteger(); if (w < 100) { Weight = 100; } else if (w >= 100 && w < 350) { Weight = 100; } else if (w >= 350 && w < 550) { Weight = 100; } else if (w >= 550 && w < 750) { Weight = 400; } else if (w >= 750 && w < 900) { Weight = 700; } else { Weight = 700; } } break; } return(CssValue.From(Weight)); }
public static CssValue Font_Size_Computed(ICssProperty Property) {/* Docs: https://www.w3.org/TR/css-fonts-3/#font-size-prop */ if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); CssValue value = (Property as CssProperty).Specified; if (value is null) { throw new CssException($"Unable to resolve absolute length for Computed \"{Property.CssName}\" value."); } Contract.EndContractBlock(); double Size = UserAgent.DEFAULT_FONT_SIZE; /* CssUIs' base font size */ double Scaling = 1.0; /* Scaling to apply to our base size, used if the specified value is a keyword */ if (value.HasValue) { if (value.IsDefinite) { Size = value.AsDecimal(); } else { switch (value.Type) { case ECssValueTypes.DIMENSION: { Scaling = 1.0; Size = value.Resolve(Property.Owner.ownerDocument.cssUnitResolver); } break; case ECssValueTypes.KEYWORD: { var keyword = value.AsEnum <EFontSize>(); switch (keyword) { /* First off, if the value is an <absolute> size keyword we associate it with a scale and apply it to our base size */ case EFontSize.XXSmall: case EFontSize.XSmall: case EFontSize.Small: case EFontSize.Medium: case EFontSize.Large: case EFontSize.XLarge: case EFontSize.XXLarge: Scaling = CssCommon.Get_Font_Size_Keyword_Scaling_Factor(keyword); break; /* Second, if the value is a <relative> size keyword we find the computed font size of our parent and increase/decrease it to get our value */ case EFontSize.Smaller: { double parentSize = Property.Owner.Style.Cascaded.FontSize.Computed.AsDecimal(); int scaleIndex = CssCommon.Get_Font_Scaling_Step_Index_From_Size(parentSize); Scaling = CssCommon.Get_Font_Scaling_From_Step_Index(scaleIndex - 1); } break; case EFontSize.Larger: { double parentSize = Property.Owner.Style.Cascaded.FontSize.Computed.AsDecimal(); int scaleIndex = CssCommon.Get_Font_Scaling_Step_Index_From_Size(parentSize); Scaling = CssCommon.Get_Font_Scaling_From_Step_Index(scaleIndex + 1); } break; } } break; } double finalSize = Size * Scaling; return(CssValue.From(finalSize)); } } // Round the size up to the nearest whole pixel value Size = CssCommon.SnapToPixel(Size); return(CssValue.From(Size)); }
public static CssValue Border_Width_Used(ICssProperty Property) {// Docs: https://www.w3.org/TR/css-backgrounds-3/#the-border-width if (Property == null) { throw new ArgumentNullException(nameof(Property)); } Contract.EndContractBlock(); var prop = (Property as CssProperty); if (prop.Computed.Type != ECssValueTypes.KEYWORD) { return(prop.Computed); } var keyword = prop.Specified.AsEnum <EBorderSize>(); int Width = 0; switch (keyword) { case EBorderSize.Thin: { Width = 1; break; } case EBorderSize.Medium: { Width = 3; break; } case EBorderSize.Thick: { Width = 5; break; } } switch (Property.CssName.EnumValue) { case ECssPropertyID.BorderLeftWidth: { if (0 != (Property.Owner.Style.Border_Left_Style & ((EBorderStyle.None | EBorderStyle.Hidden)))) { return(CssValue.From(0, ECssUnit.PX)); } } break; case ECssPropertyID.BorderTopWidth: { if (0 != (Property.Owner.Style.Border_Top_Style & ((EBorderStyle.None | EBorderStyle.Hidden)))) { return(CssValue.From(0, ECssUnit.PX)); } } break; case ECssPropertyID.BorderRightWidth: { if (0 != (Property.Owner.Style.Border_Right_Style & ((EBorderStyle.None | EBorderStyle.Hidden)))) { return(CssValue.From(0, ECssUnit.PX)); } } break; case ECssPropertyID.BorderBottomWidth: { if (0 != (Property.Owner.Style.Border_Bottom_Style & ((EBorderStyle.None | EBorderStyle.Hidden)))) { return(CssValue.From(0, ECssUnit.PX)); } } break; } return(CssValue.From(Width, ECssUnit.PX)); }