private static void FillStyleSheet(TextReader reader, CssStyleSheet styleSheet, Func <string, TextReader> getImport) { using (var enumerator = CssReader.Read(reader).GetEnumerator()) { if (!enumerator.MoveNext()) { return; } CssRule rule; while (enumerator.Current.Type == CssChunkTypes.Directive && enumerator.Current.Data != null && enumerator.Current.Data.StartsWith("import ")) { var dirrective = enumerator.Current.Data; var import = dirrective.Substring(7); Import(styleSheet, import, getImport); enumerator.MoveNext(); } while (CreateRule(styleSheet, enumerator, out rule)) { if (rule != null) { styleSheet.CssRules.Add(rule); } } if (rule != null) { styleSheet.CssRules.Add(rule); } } }
public void Parse(CssReader reader, GradientBuilder builder) { var isRepeating = reader.Read().Trim() == CssToken.RepeatingRadialGradient; var token = reader.ReadNext().Trim(); var internalReader = new CssReader(token, ' '); var flags = None; var(hasShape, shape) = GetShape(internalReader); var(hasSize, size) = GetSize(internalReader); var(hasRadius, radius) = GeRadius(internalReader, shape, ref flags); var(hasPos, position) = GetPosition(internalReader, ref flags); builder.UseBuilder(new RadialGradientBuilder { Center = position, Shape = shape, Size = size, RadiusX = radius.Width, RadiusY = radius.Height, Flags = flags, IsRepeating = isRepeating }); if (!hasShape && !hasSize && !hasRadius && !hasPos) { reader.Rollback(); } }
public void Parse(CssReader reader, GradientBuilder builder) { var isRepeating = reader.Read().Trim() == CssToken.RepeatingRadialGradient; var token = reader.ReadNext().Trim(); var internalReader = new CssReader(token, ' '); var(hasShape, shape) = GetShape(internalReader); var(hasStretch, stretch) = GetStretch(internalReader); var(hasRadius, radius) = GeRadius(internalReader, shape); var(hasPos, position) = GetPosition(internalReader); builder.UseBuilder(new RadialGradientBuilder { Center = position, Shape = shape, Stretch = stretch, Radius = radius, IsRepeating = isRepeating }); if (!hasShape && !hasStretch && !hasRadius && !hasPos) { reader.Rollback(); } }
internal bool TryConvertNamedDirectionToAngle(string token, out double angle) { var reader = new CssReader(token, ' '); if (reader.CanRead && reader.Read() == "to") { var defaultVector = Vector2.Down; // By default gradient is drawn top-down var directionVector = Vector2.Zero; reader.MoveNext(); while (reader.CanRead) { directionVector.SetNamedDirection(reader.Read()); reader.MoveNext(); } angle = Vector2.Angle(ref defaultVector, ref directionVector); // We start rotation from Vector(0, -1) clockwise // If gradient ends in I or II quarter of coordinate system // we use angle to calculate actual rotation if (directionVector.X > 0) { angle = 360 - angle; } return(true); } angle = 0; return(false); }
private Point GetPosition(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Trim(); if (token == "at") { var tokenX = reader.ReadNext(); var tokenY = reader.ReadNext(); var isPosX = tokenX.TryConvertOffset(out var posX); var isPosY = tokenY.TryConvertOffset(out var posY); var direction = Vector2.Zero; if (!isPosX && !string.IsNullOrEmpty(tokenX)) { direction.SetNamedDirection(tokenX); } if (!isPosY && !string.IsNullOrEmpty(tokenY)) { direction.SetNamedDirection(tokenY); } return(new Point( isPosX ? posX : (direction.X + 1) / 2, isPosY ? posY : (direction.Y + 1) / 2)); } } return(new Point(0.5, 0.5)); }
private (bool, Size) GeRadius(CssReader reader, RadialGradientShape shape, ref RadialGradientFlags flags) { if (reader.CanRead) { var size = Dimensions.Zero; if (shape == RadialGradientShape.Circle) { var radiusToken = reader.Read(); var isRadius = OffsetConverter.TryExtractOffset(radiusToken, out var radius); if (isRadius) { size = new Dimensions(radius, radius); reader.MoveNext(); } } if (shape == RadialGradientShape.Ellipse) { var radiusHToken = reader.Read(); var radiusVToken = reader.ReadNext(); var isRadiusH = OffsetConverter.TryExtractOffset(radiusHToken, out var radiusH); var isRadiusV = OffsetConverter.TryExtractOffset(radiusVToken, out var radiusV); if (isRadiusH && isRadiusV) { size = new Dimensions(radiusH, radiusV); reader.MoveNext(); } else { // Revert radiusVToken reader.Rollback(); } } if (size != Dimensions.Zero) { if (size.Width.Type == OffsetType.Proportional) { FlagsHelper.Set(ref flags, WidthProportional); } if (size.Height.Type == OffsetType.Proportional) { FlagsHelper.Set(ref flags, HeightProportional); } return(true, new Size(size.Width.Value, size.Height.Value)); } } // Value -1 means undefined for RadialGradientShader return(false, new Size(-1, -1)); }
public void GetColorString_ReadFromCssReader_CorrectColorStringReturned(string colorInCss) { // Arrange var definition = new ColorChannelDefinition(); var reader = new CssReader(colorInCss); // Act var colorInString = definition.GetColorString(reader); // Assert colorInString.Should().Be(colorInCss); }
public void Parse_HslAndHsla_WithDoubleValues_NoExceptionsThrown(string color) { // Arrange var reader = new CssReader(color); var builder = new GradientBuilder(); var definition = new ColorChannelDefinition(); // Act Action action = () => definition.Parse(reader, builder); // Assert action.Should().NotThrow <Exception>(); }
public void Parse(CssReader reader, LinearGradientBuilder builder) { var color = (Color)ColorConverter.ConvertFromInvariantString(GetColorString(reader)); if (TryConvertPercentToOffset(reader.ReadNext(), out var offset)) { builder.AddStop(color, offset); } else { builder.AddStop(color); reader.Rollback(); } }
public void Parse(CssReader reader, GradientBuilder builder) { var isRepeating = reader.Read().Trim() == CssToken.RepeatingRadialGradient; var token = reader.ReadNext().Trim(); var internalReader = new CssReader(token, ' '); var shape = GetShape(internalReader); var shapeSize = GetShapeSize(internalReader); var(position, flags) = GetPositionWithFlags(internalReader); builder.AddRadialGradient(position, shape, shapeSize, flags, isRepeating); }
public void Parse(CssReader reader, GradientBuilder builder) { var parts = reader.Read().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var color = (Color)ColorConverter.ConvertFromInvariantString(parts[0]); if (parts.TryConvertOffsets(out var offsets)) { builder.AddStops(color, offsets); } else { builder.AddStop(color); } }
private RadialGradientShape GetShape(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Trim(); if (Enum.TryParse <RadialGradientShape>(token, true, out var shape)) { reader.MoveNext(); return(shape); } } return(RadialGradientShape.Ellipse); }
public void Parse(CssReader reader, GradientBuilder builder) { var parts = reader.Read().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var color = GetNamedColor(parts[0]); var offsets = GetOffsets(parts); if (offsets.Any()) { builder.AddStops(color, offsets); } else { builder.AddStop(color); } }
private RadialGradientSize GetShapeSize(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Replace("-", "").Trim(); if (Enum.TryParse <RadialGradientSize>(token, true, out var shapeSize)) { reader.MoveNext(); return(shapeSize); } } return(RadialGradientSize.FarthestCorner); }
private (bool, RadialGradientStretch) GetStretch(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Replace("-", "").Trim(); if (Enum.TryParse <RadialGradientStretch>(token, true, out var stretch)) { reader.MoveNext(); return(true, stretch); } } return(false, RadialGradientStretch.FarthestCorner); }
private (Point, RadialGradientFlags) GetPositionWithFlags(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Trim(); if (token == "at") { var tokenX = reader.ReadNext(); var tokenY = reader.ReadNext(); var isPosX = OffsetConverter.TryExtractOffset(tokenX, out var posX); var isPosY = OffsetConverter.TryExtractOffset(tokenY, out var posY); var direction = Vector2.Zero; if (!isPosX && !string.IsNullOrEmpty(tokenX)) { direction.SetNamedDirection(tokenX); } if (!isPosY && !string.IsNullOrEmpty(tokenY)) { direction.SetNamedDirection(tokenY); } var flags = None; if (!isPosX || posX.Type == OffsetType.Proportional) { flags |= XProportional; } if (!isPosY || posY.Type == OffsetType.Proportional) { flags |= YProportional; } var center = new Point( isPosX ? posX.Value : (direction.X + 1) / 2, isPosY ? posY.Value : (direction.Y + 1) / 2); return(center, flags); } } return(new Point(0.5, 0.5), PositionProportional); }
private (bool, Point) GetPosition(CssReader reader, ref RadialGradientFlags flags) { if (reader.CanRead) { var token = reader.Read().Trim(); if (token == "at") { var tokenX = reader.ReadNext(); var tokenY = reader.ReadNext(); var isPosX = OffsetConverter.TryExtractOffset(tokenX, out var posX); var isPosY = OffsetConverter.TryExtractOffset(tokenY, out var posY); var direction = Vector2.Zero; if (!isPosX && !string.IsNullOrEmpty(tokenX)) { direction.SetNamedDirection(tokenX); } if (!isPosY && !string.IsNullOrEmpty(tokenY)) { direction.SetNamedDirection(tokenY); } if (!isPosX || posX.Type == OffsetType.Proportional) { FlagsHelper.Set(ref flags, XProportional); } if (!isPosY || posY.Type == OffsetType.Proportional) { FlagsHelper.Set(ref flags, YProportional); } var center = new Point( isPosX ? posX.Value : (direction.X + 1) / 2, isPosY ? posY.Value : (direction.Y + 1) / 2); return(true, center); } } FlagsHelper.Set(ref flags, PositionProportional); return(false, new Point(0.5, 0.5)); }
public void Parse(CssReader reader, GradientBuilder builder) { var colorString = GetColorString(reader); var color = (Color)ColorConverter.ConvertFromInvariantString(colorString); var parts = reader.ReadNext().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var offsets = GetOffsets(parts); if (offsets.Any()) { builder.AddStops(color, offsets); } else { builder.AddStop(color); reader.Rollback(); } }
private (bool, Dimensions) GeRadius(CssReader reader, RadialGradientShape shape) { if (reader.CanRead) { var size = Dimensions.Zero; if (shape == RadialGradientShape.Circle) { var radiusToken = reader.Read(); var isRadius = Offset.TryParseWithUnit(radiusToken, out var radius); if (isRadius) { size = new Dimensions(radius, radius); reader.MoveNext(); } } if (shape == RadialGradientShape.Ellipse) { var radiusHToken = reader.Read(); var radiusVToken = reader.ReadNext(); var isRadiusH = Offset.TryParseWithUnit(radiusHToken, out var radiusH); var isRadiusV = Offset.TryParseWithUnit(radiusVToken, out var radiusV); if (isRadiusH && isRadiusV) { size = new Dimensions(radiusH, radiusV); reader.MoveNext(); } else { // Revert radiusVToken reader.Rollback(); } } if (size != Dimensions.Zero) { return(true, size); } } return(false, Dimensions.Zero); }
public void Parse(CssReader reader, LinearGradientBuilder builder) { var parts = reader.Read().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var color = parts.Length > 0 ? (Color)ColorConverter.ConvertFromInvariantString(parts[0]) : Color.Black; if (parts.Length > 1 && TryConvertPercentToOffset(parts[1], out var offset)) { builder.AddStop(color, offset); } else { builder.AddStop(color); } }
public void Parse(CssReader reader, LinearGradientBuilder builder) { var direction = reader.ReadNext().Trim(); if (TryConvertDegreeToAngle(direction, out var degreeToAngle)) { builder.AddGradient(degreeToAngle); } else if (TryConvertNamedDirectionToAngle(direction, out var directionToAngle)) { builder.AddGradient(directionToAngle); } else { builder.AddGradient(0); reader.Rollback(); } }
public void Parse(CssReader reader, GradientBuilder builder) { var repeating = reader.Read().Trim() == CssToken.RepeatingLinearGradient; var direction = reader.ReadNext().Trim(); var angle = 0d; var hasAngle = TryConvertDegreeToAngle(direction, out angle) || TryConvertTurnToAngle(direction, out angle) || TryConvertNamedDirectionToAngle(direction, out angle); if (hasAngle) { builder.AddLinearGradient(angle, repeating); } else { builder.AddLinearGradient(0, repeating); reader.Rollback(); } }
public void Parse(CssReader reader, GradientBuilder builder) { var repeating = reader.Read().Trim() == CssToken.RepeatingLinearGradient; var direction = reader.ReadNext().Trim(); var angle = 0d; var hasAngle = TryConvertDegreeToAngle(direction, out angle) || TryConvertTurnToAngle(direction, out angle) || TryConvertNamedDirectionToAngle(direction, out angle); builder.UseBuilder(new LinearGradientBuilder { Angle = angle, IsRepeating = repeating }); if (!hasAngle) { reader.Rollback(); } }
public void Parse_ValidGradientCss_ExpectedGradientReturned(string css, LinearGradient expectedGradient) { // Arrange var reader = new CssReader(css); var builder = new GradientBuilder(); var definition = new LinearGradientDefinition(); // Act definition.Parse(reader, builder); // Assert var result = builder.Build(); using (new AssertionScope()) { result.Should().HaveCount(1); var linearGradient = result[0] as LinearGradient; linearGradient.Should().NotBeNull(); linearGradient.Should().BeEquivalentTo(expectedGradient); } }
public void Parse_ValidColor_SingleStopWithColorAndOffset(string color, Color expectedColor, float expectedOffset) { // Arrange var reader = new CssReader(color); var builder = new LinearGradientBuilder(); var definition = new ColorChannelDefinition(); // Act definition.Parse(reader, builder); // Assert var result = builder.Build(); using (new AssertionScope()) { var stops = result.SelectMany(x => x.Stops).ToArray(); stops.Should().HaveCount(1); stops[0].Color.Should().Be(expectedColor); stops[0].Offset.Should().Be(expectedOffset); } }
internal string GetColorString(CssReader reader) { var token = reader.Read().Trim(); var builder = new StringBuilder(token); builder.Append('('); builder.Append(reader.ReadNext()); builder.Append(','); builder.Append(reader.ReadNext()); builder.Append(','); builder.Append(reader.ReadNext()); if (token == CssToken.Rgba || token == CssToken.Hsla) { builder.Append(','); builder.Append(reader.ReadNext()); } builder.Append(')'); return(builder.ToString()); }
private (bool, Position) GetPosition(CssReader reader) { if (reader.CanRead) { var token = reader.Read().Trim(); if (token == "at") { var tokenX = reader.ReadNext(); var tokenY = reader.ReadNext(); var isPosX = Offset.TryParseWithUnit(tokenX, out var posX); var isPosY = Offset.TryParseWithUnit(tokenY, out var posY); var direction = Vector2.Zero; if (!isPosX && !string.IsNullOrEmpty(tokenX)) { direction.SetNamedDirection(tokenX); } if (!isPosY && !string.IsNullOrEmpty(tokenY)) { direction.SetNamedDirection(tokenY); } var center = new Position( isPosX ? posX : Offset.Prop((direction.X + 1) / 2), isPosY ? posY : Offset.Prop((direction.Y + 1) / 2)); return(true, center); } } return(false, Position.Prop(0.5, 0.5)); }
public static void FillStyle(CssStyleDeclaration style, string str) { if (str[0] != '{') { str = '{' + str; } str = "toskip" + str; if (str.Last() != '}') { str += '}'; } using (var enumerator = CssReader.Read(new StringReader(str)).GetEnumerator()) { //skip selector while (enumerator.MoveNext() && enumerator.Current.Type == CssChunkTypes.Selector) { ; } FillStyle(style, enumerator); } }
public void ReadCss(string css, string result) { var res = CssReader.Read(new StringReader(css)).Select(x => x.Type.ToString() + ":" + (x.Data ?? "")).ToArray(); Assert.AreEqual(result, string.Join(" ", res)); }