/// <summary> /// Adds all of the set flags from the given collection to this one /// </summary> public void And(FlagCollection <FlagType> Right) { unsafe { for (int i = 0; i < Size; i++) { ChunkData[i] &= Right.ChunkData[i]; } /// There's no smart way to determine this, we have to do it manually ActiveFlags = Tally_Active(); } }
/// <summary> /// Returns a new collection with all flags that are in either this or the other collection but not both /// </summary> public static FlagCollection <FlagType> operator ^(FlagCollection <FlagType> Left, FlagCollection <FlagType> Right) { var RetVal = new FlagCollection <FlagType>(Left.Length); unsafe { for (int i = 0; i < Left.Size; i++) { RetVal.ChunkData[i] = Left.ChunkData[i] ^ Right.ChunkData[i]; } } return(RetVal); }
/// <summary> /// Returns <c>True</c> if the given collection also has all of this collections active flags set /// </summary> public bool IsSubsetOf(FlagCollection <FlagType> Right) { return((this & Right) == this); }
/// <summary> /// Resolves all Css properties to their specified values by cascading /// </summary> public void Cascade() { /* XXX: LOTS of room for speed improvement here. We should avoid using LINQ statements in performance critical areas like this. */ var benchmark_id = Benchmark.Start("style-cascade"); // Get a list of only the properties with an Assigned value AsyncCountdownEvent ctdn = null; /* * HashSet<AtomicName<ECssPropertyID>> targetFields = new HashSet<AtomicName<ECssPropertyID>>(); * List<HashSet<AtomicName<ECssPropertyID>>> allFields = CssRules.Values.Select(x => { return x.SetProperties; }).ToList(); */ var targetFields = new FlagCollection <ECssPropertyID>((int)ECssPropertyID.MAX_VALUE); List <FlagCollection <ECssPropertyID> > allFields = CssRules.Values.Select(x => { return(x.SetProperties); }).ToList(); // Remove duplicates //foreach (HashSet<AtomicName<ECssPropertyID>> fields in allFields) foreach (FlagCollection <ECssPropertyID> fields in allFields) { targetFields.And(fields); } if (targetFields.ActiveFlags > 0) { // Cascade all those set values ctdn = new AsyncCountdownEvent(targetFields.ActiveFlags); // Loop over all target properties foreach (int flagIndex in targetFields) //Parallel.ForEach(targetFields, async (AtomicString propName) => { try { AtomicName <ECssPropertyID> propName = new AtomicName <ECssPropertyID>(flagIndex); // Extract this property from every CssPropertySet that has a value for it var propertyList = CssRules.Values.Select(x => { return(x.Get(propName)); }).ToList(); // Order these properties according to CSS 3.0 specifications propertyList.Sort(CssPropertyComparator.Instance); /* * // Because cascading overwrites an existing value with the one from the next propertyset we need to reverse this list. * propertyList.Reverse();*/ // Cascade this list and get what CSS calls the 'Specified' value ICssProperty Value = Cascaded.Get(propName); foreach (ICssProperty o in propertyList) { //bool b = await Value.CascadeAsync(o); bool b = Value.Cascade(o); if (b) { break; // stop cascading the instant we find a set value } } string SourceState = Value.Source.ToString(); //await Cascaded.Set(propName, Value); Cascaded.Set(propName, Value); } finally { ctdn.Signal(); } //}); } ctdn.WaitAsync().Wait(); } // Recalculate ALL properties var PropList = Cascaded.GetAll().ToList(); /*ctdn = new AsyncCountdownEvent(PropList.Count); * Parallel.For(0, PropList.Count, (int i) => * { * ICssProperty prop = PropList[i]; * // We always want to compute these now to get their values resolved. otherwise any with just assigned values will not interpret and output computed values. * prop.Update(ComputeNow: true); * ctdn.Signal(); * }); * ctdn.WaitAsync().Wait();*/ for (int i = 0; i < PropList.Count; i++) { ICssProperty prop = PropList[i]; // We always want to compute these now to get their values resolved. otherwise any with just assigned values will not interpret and output computed values. prop.Update(ComputeNow: true); } // Any values that changed due to this cascade should have thrown a property change event to let the style system know what it needs to update // Remove cascade flag ClearFlag(EPropertySystemDirtFlags.NeedsToCascade); Benchmark.Stop(benchmark_id); }