/// <summary>A special variant of clone which checks if the inherited value is a set /// (and if it is a set, this returns a set of inherits).</summary> public Css.Value SetCopy() { // Either we're inheriting nothing, it's not a set, or the property is atomic: if (From_ == null || !(From_ is Css.ValueSet) || Property.AliasedProperties == null) { // Ordinary copy: return(Copy()); } // Create a set of inherits: int count = Count; Css.ValueSet vs = Activator.CreateInstance(From_.GetType()) as Css.ValueSet; vs.Count = count; for (int i = 0; i < count; i++) { // Get the aliased property (e.g. color-r): CssProperty aliasedProperty = Property.GetAliased(i, false); if (aliasedProperty == null) { // Use the original value: vs[i] = From_[i]; } else { // Create: Inherit inh = new Inherit(aliasedProperty); // Get the actual value: inh.From_ = From_[i]; // Add to set: vs[i] = inh; } } return(vs); }
/// <summary>Loads a gradient from a set of stops in the given parameters.</summary> public static Gradient2D LoadGradient(int firstColour, Css.ValueSet parameters, bool autoRepeat) { // Next load the stops. int paramCount = parameters.Count; int stopCount = paramCount - firstColour; int lastColour = paramCount - 1; // Create the gradient: Gradient2D grad = new Gradient2D(stopCount); int index = 0; int undefinedPoints = 0; for (int i = firstColour; i < paramCount; i++) { // Get the stop value: Css.Value stop = parameters[i]; // It's either a set (colour and stop) or just a colour. Color colour; float stopValue; if (stop is Css.Units.ColourUnit) { // Pull the colour: colour = stop.GetColour(); if (i == lastColour) { stopValue = 1f; } else if (i == firstColour) { stopValue = 0f; } else { stopValue = float.MaxValue; } } else { // Pull the colour: colour = stop[0].GetColour(); // And the stop %: stopValue = stop[1].GetRawDecimal(); } // Drop in the colour: grad.Colours[index] = colour; if (stopValue == float.MaxValue) { // This point doesn't have a stop value defined. // We'll have to load the following ones first and come back to it. undefinedPoints++; } else { // Define any undefined points now: if (undefinedPoints != 0) { // First undefined point is.. int firstUndef = index - undefinedPoints; // Get the previously defined position: float lastDefined = grad.Positions[firstUndef - 1]; // Delta is therefore.. float delta = (stopValue - lastDefined) / (float)(undefinedPoints + 1); // For each undefined point.. for (int undef = 0; undef < undefinedPoints; undef++) { // Bump up the defined amount: lastDefined += delta; // Set the position: grad.Positions[firstUndef + undef] = lastDefined; } // Clear: undefinedPoints = 0; } // Set the position: grad.Positions[index] = stopValue; } index++; } return(grad); }
/// <summary>Loads this systems values from the given style.</summary> public void Load(Css.Style style, Css.ReflowDocument document) { // Get the range: Css.Value range = style[Css.Properties.RangeProperty.GlobalProperty]; if (range != null && !range.IsAuto) { Css.ValueSet rangeSet = range as Css.ValueSet; int rangeSize = (rangeSet != null && rangeSet.Spacer == ",")?range.Count : 1; if (rangeSize > 1) { AdditionalRanges = new CounterRange[rangeSize]; int overallMin = 0; int overallMax = 0; // For each one.. for (int i = 0; i < rangeSize; i++) { int min = range[i][0].GetInteger(null, null); int max = range[i][1].GetInteger(null, null); if (i == 0) { overallMin = min; overallMax = max; } else { if (min < overallMin) { overallMin = min; } if (max > overallMax) { overallMax = max; } } AdditionalRanges[i] = new CounterRange(min, max); } Min = overallMin; Max = overallMax; } else { AdditionalRanges = null; // Set min/max: Min = range[0].GetInteger(null, null); Max = range[1].GetInteger(null, null); } } // Get the pad: Css.Value pad = style[Css.Properties.Pad.GlobalProperty]; if (pad != null) { PadMin = pad[0].GetInteger(null, null); if (pad is Css.ValueSet) { PadSymbol = pad[1].Text; } else { PadSymbol = ""; } } // Prefix: Css.Value prefix = style[Css.Properties.Prefix.GlobalProperty]; if (prefix != null) { Prefix = prefix.Text; } // Suffix: Css.Value suffix = style[Css.Properties.Suffix.GlobalProperty]; if (suffix != null) { Suffix = suffix.Text; } // Negative: Css.Value negative = style[Css.Properties.Negative.GlobalProperty]; if (negative != null) { NegativePrefix = negative[0].Text; if (negative is Css.ValueSet) { NegativeSuffix = negative[1].Text; } else { NegativeSuffix = ""; } } // Symbols: LoadSymbols(style); // Fallback: Css.Value fallback = style[Css.Properties.Fallback.GlobalProperty]; if (fallback != null) { string fbName = fallback[0].Text; if (fbName == "none" || fbName == "decimal") { fbName = null; } if (fbName != null) { // Get by built in name: Fallback = Counters.CounterSystems.Get(fbName); if (Fallback == null) { // Get by doc name: CounterStyleRule rule; if (document.CssCounters.TryGetValue(fbName, out rule)) { // Get the system: Fallback = rule.System; } } } if (Fallback == null) { // Default to decimal system: Fallback = CounterSystems.Decimal; } } }
/// <summary>Gets or creates the base value for the given property. /// The base value is essentially the value held directly in this style sheet. /// E.g. if the value you're setting is the R channel of color-overlay, this sets up the color-overlay value for you.</summary> /// <returns>The raw value (which may have just been created). Never an 'inherit' or 'initial' keyword.</returns> internal Css.Value GetBaseValue(CssProperty property) { Css.Value propertyValue; // Does it exist already? if (!Properties.TryGetValue(property, out propertyValue)) { // Nope! Create it now. Does the computed style hold a value instead? ComputedStyle computed = GetComputed(); if (computed != null && computed.Properties.TryGetValue(property, out propertyValue) && propertyValue != null) { // Derive from the computed value. if (propertyValue is Css.Keywords.Inherit) { // Must clone the inherited value (using special inherit copy): propertyValue = (propertyValue as Css.Keywords.Inherit).SetCopy(); } else if (propertyValue is Css.Keywords.Initial) { // Clone the initial value: propertyValue = property.InitialValue.Copy(); } else { // Must copy it: propertyValue = propertyValue.Copy(); } // Make sure it has low specif: propertyValue.Specifity = -1; } else { // Needs to be created. Must also copy it. // Copy is used because it'll probably change some internal value. propertyValue = property.InitialValue.Copy(); } Properties[property] = propertyValue; } else if (propertyValue is Css.Keywords.Inherit) { // Must clone the inherited value (using special inherit copy): propertyValue = (propertyValue as Css.Keywords.Inherit).SetCopy(); // Make sure it has low specif: propertyValue.Specifity = -1; Properties[property] = propertyValue; } else if (propertyValue is Css.Keywords.Initial) { // Clone the initial value: propertyValue = property.InitialValue.Copy(); // Make sure it has low specif: propertyValue.Specifity = -1; Properties[property] = propertyValue; } // If it's not currently a set, we need it as one. int size = property.SetSize; if (propertyValue is Css.ValueSet) { if (propertyValue.Count < size) { // Resize it: propertyValue.Count = size; } } else { // Create the set: Css.ValueSet set = new Css.ValueSet(); set.Count = size; // Make sure it has low specif: set.Specifity = -1; for (int i = 0; i < size; i++) { // Must copy each value (e.g. if they get animated): set[i] = propertyValue.Copy(); } Properties[property] = set; propertyValue = set; } return(propertyValue); }