コード例 #1
0
        /// <summary>
        /// Check if the whole cluster is complex enough such that rasterizing the whole thing is better than flattening it
        /// </summary>
        /// <param name="commands"></param>
        /// <returns></returns>
        private bool BetterRasterize(List <PrimitiveInfo> commands)
        {
            double clustersize = m_bounds.Width * m_bounds.Height;

            double diff = -Configuration.RasterizationCost(m_bounds.Width, m_bounds.Height);

            // Estimate cost of geometry operations (intersecting)
            double pathComplexity = 1;

            foreach (int i in m_primitives)
            {
                PrimitiveInfo pi = commands[i];

                Primitive p = pi.primitive;

                GeometryPrimitive gp = p as GeometryPrimitive;

                Rect bounds = pi.GetClippedBounds();

                bool rasterize = true;

                if (gp != null)
                {
                    double complexity = 1;

                    Geometry geo = gp.Geometry;

                    if (geo != null)
                    {
                        complexity = Utility.GetGeometryPointCount(geo);

                        // weight down the complexity of small region
                        complexity *= bounds.Width * bounds.Height / clustersize;
                    }

                    BrushProxy bp = gp.Brush;

                    if (bp == null)
                    {
                        bp = gp.Pen.StrokeBrush;

                        // Widen path would at least double the points
                        complexity *= 3;
                    }

                    if (complexity > 1)
                    {
                        pathComplexity *= complexity;

                        if (pathComplexity > 100000) // 333 x 333
                        {
                            return(true);
                        }
                    }

                    if (bp != null)
                    {
                        Brush b = bp.Brush;

                        if ((b != null) && ((b is SolidColorBrush) || (b is LinearGradientBrush)))
                        {
                            // SolidColorBrush does not need full rasterization
                            // Vertical/Horizontal linear gradient brush does not need full rasterization
                            rasterize = false;
                        }
                    }
                }

                if (rasterize)
                {
                    diff += Configuration.RasterizationCost(bounds.Width, bounds.Height);

                    if (diff > 0)
                    {
                        break;
                    }
                }
            }

            return(diff > 0);
        }
コード例 #2
0
        /// <summary>
        /// Calculates list of transparent clusters, returning true if clusters added or bounding rectangles changed.
        /// </summary>
        private static bool CalculateClusterCore(
            List <PrimitiveInfo> commands,
            int count,
            bool disjoint,
            List <int> [] oldUnderlay,
            List <Cluster> transparentCluster,
            bool[] addedPrimitives      // primitives added to clusters
            )
        {
            bool clusterBoundsChanged = false;

            // Build clusters of transparent primitives
            for (int i = 0; i < count; i++)
            {
                PrimitiveInfo pi = commands[i];

                // When disjoint is true (flattening a subtree), add all primitives to a single cluster
                if ((pi != null) && (disjoint || !pi.primitive.IsOpaque) && !addedPrimitives[i])
                {
                    Rect bounds = pi.GetClippedBounds();

                    Cluster home = null;

                    for (int j = 0; j < transparentCluster.Count; j++)
                    {
                        Cluster c = transparentCluster[j];

                        if (disjoint || bounds.IntersectsWith(c.m_bounds))
                        {
                            home = c;
                            break;
                        }
                    }

                    if (home == null)
                    {
                        home = new Cluster();
                        transparentCluster.Add(home);
                    }

                    Rect oldClusterBounds = home.m_bounds;

                    home.Add(i, oldUnderlay, commands, addedPrimitives);

                    if (!clusterBoundsChanged && oldClusterBounds != home.m_bounds)
                    {
                        // cluster bounds have changed
                        clusterBoundsChanged = true;
                    }
                }
            }

            // Merges clusters which touch each other
            bool changed;

            do
            {
                changed = false;

                for (int i = 0; i < transparentCluster.Count; i++)
                {
                    for (int j = i + 1; j < transparentCluster.Count; j++)
                    {
                        if (transparentCluster[i].m_bounds.IntersectsWith(transparentCluster[j].m_bounds))
                        {
                            transparentCluster[i].MergeWith(transparentCluster[j]);

                            // cluster bounds have changed since merging two clusters
                            clusterBoundsChanged = true;

                            transparentCluster.RemoveAt(j);
                            changed = true;
                            break;
                        }
                    }
                }
            }while (changed);

            return(clusterBoundsChanged);
        }
コード例 #3
0
        public static List <Cluster> CalculateCluster(List <PrimitiveInfo> commands, int count, bool disjoint, List <int>[] oldUnderlay)
        {
            List <Cluster> transparentCluster = new List <Cluster>();

            // indicates which primitives have been added to any cluster
            bool[] addedPrimitives = new bool[commands.Count];

            // calculate clusters until cluster bounds stabilize
            while (true)
            {
                bool clusterBoundsChanged = CalculateClusterCore(
                    commands,
                    count,
                    disjoint,
                    oldUnderlay,
                    transparentCluster,
                    addedPrimitives
                    );

                if (!clusterBoundsChanged || GetPrimitiveIntersectAction() != PrimitiveIntersectAction.AddToCluster)
                {
                    break;
                }

                //
                // Cluster bounds have changed somewhere, need to examine all primitives that haven't
                // been added to a cluster and test for intersection with cluster. We add primitives
                // that intersect and rendered before the cluster.
                //
                // Note that here we check even opaque primitives, since they might get covered
                // by a transparent cluster, and thus need to be rasterized with a cluster if intersection
                // exists.
                //
                for (int primIndex = 0; primIndex < addedPrimitives.Length; primIndex++)
                {
                    if (!addedPrimitives[primIndex] && commands[primIndex] != null)
                    {
                        PrimitiveInfo primitive = commands[primIndex];

                        for (int clusterIndex = 0; clusterIndex < transparentCluster.Count; clusterIndex++)
                        {
                            Cluster cluster = transparentCluster[clusterIndex];

                            if (primitive.GetClippedBounds().IntersectsWith(cluster.m_bounds) &&
                                primIndex < cluster.m_lowestPrimitive)
                            {
                                // primitive intersects this cluster, add to cluster
                                cluster.Add(
                                    primIndex,
                                    oldUnderlay,
                                    commands,
                                    addedPrimitives
                                    );
                            }
                        }
                    }
                }
            }

            return(transparentCluster);
        }