File: AlphaFlattener\PrimitiveList.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
 
 
using System;
using System.Diagnostics;
using System.Collections;              // for ArrayList
using System.Windows;                  // for Rect                        WindowsBase.dll
using System.Windows.Media;            // for Geometry, Brush, ImageData. PresentationCore.dll
using System.Globalization;
using System.Text;
using System.Collections.Generic;
 
namespace Microsoft.Internal.AlphaFlattener
{
    internal class DisplayList 
    {
        public bool   m_DisJoint;
        public double m_width;
        public double m_height;
 
        public DisplayList(bool disJoint, double width, double height)
        {
            m_DisJoint       = disJoint;
            m_width          = width;
            m_height         = height;
        }
 
        #region Public Methods
 
#if DEBUG
        static int overlapcount;
 
        internal static string LeftPad(object obj, int len)
        {
            string s;
        
            List<int> l = obj as List<int>;
 
            if (l != null)
            {
                s = "<";
 
                foreach (int i in l)
                {
                    if (s.Length > 1)
                    {
                        s = s + ' ';
                    }
                    
                    s = s + i;
                }
 
                return s + ">";
            }
            else if (obj is Double)
            {
                s = ((Double)obj).ToString("F1", CultureInfo.InvariantCulture);
            }
            else if (obj is Rect)
            {
                Rect r = (Rect) obj;
 
                return " [" + LeftPad(r.Left,   6) + ' '
                            + LeftPad(r.Top,    6) + ' '
                            + LeftPad(r.Width,  6) + ' '
                            + LeftPad(r.Height, 6) + "]";
            }
            else
            {
                s = obj.ToString();
            }
 
            return s.PadLeft(len, ' ');
        }
 
        static internal void PrintPrimitive(PrimitiveInfo info, int index, bool verbose)
        {
            if (index < 0)
            {
                Console.WriteLine();
 
                Console.WriteLine(" No      Type           Und Ovr TrO           Bounding Box                   Clipping");
        
                if (verbose)
                {
                    Console.Write("                     Transform");
                }
 
                Console.WriteLine();
                return;
            }
            
            Primitive p = info.primitive;
 
            string typ = p.GetType().ToString();
 
            typ = typ.Substring(typ.LastIndexOf('.') + 1);
 
            Console.Write(LeftPad(index, 4) + LeftPad(typ, 18) + ":");
            
            List<int> extra = null;
 
            if (p.IsOpaque)
            {
                Console.Write(' ');
            }
            else
            {
                Console.Write('@');
            }
 
            if (info.underlay == null)
            {
                Console.Write("   ");
            }
            else
            {
                extra = info.underlay;
 
                Console.Write(LeftPad(info.underlay.Count, 3));
            }
 
            if (info.overlap != null)
            {
                Console.Write(' ' + LeftPad(info.overlap.Count, 3));
 
                if (info.overlapHasTransparency != 0)
                {
                    Console.Write('$');
                    Console.Write(LeftPad(info.overlapHasTransparency, 3));
                }
                else
                {
                    Console.Write("    ");
                }
 
                Console.Write(' ');
            }
            else
            {
                Console.Write("         ");
            }
            
            Console.Write(LeftPad(info.bounds, 0));
            
            Geometry clip = p.Clip;
 
            if (clip != null)
            {
                Console.Write(LeftPad(clip.Bounds, 0));
            }
            
            if (verbose)
            {
                Matrix m = p.Transform;
 
                Console.Write(" {");
                Console.Write(LeftPad(m.M11, 3) + ' ');
                Console.Write(LeftPad(m.M12, 3) + ' ');
                Console.Write(LeftPad(m.M21, 3) + ' ');
                Console.Write(LeftPad(m.M22, 3) + ' ');
                Console.Write(LeftPad(m.OffsetX, 6) + ' ');
                Console.Write(LeftPad(m.OffsetY, 6));
                Console.Write("} ");
            }
            
            if (verbose)
            {
                GlyphPrimitive gp = p as GlyphPrimitive;
 
                if (gp != null)
                {
                    IList<char> chars = gp.GlyphRun.Characters;
                                
                    Console.Write(" \"");
 
                    for (int i = 0; i < chars.Count; i ++)
                    {
                        Console.Write(chars[i]);
                    }
                    
                    Console.Write('"');
                }
            }
 
            if (verbose)
            {
                GeometryPrimitive gp = p as GeometryPrimitive;
 
                if ((gp != null) && (gp.Brush != null) && (gp.Pen == null))
                {
                    Brush b = gp.Brush.Brush;
 
                    if (b != null)
                    {
                        SolidColorBrush sb = b as SolidColorBrush;
 
                        if (sb != null)
                        {
                            Console.Write(" SolidColorBrush({0})", sb.Color);
                        }
                    }
                }
            }
 
            if (extra != null)
            {
                Console.Write(' ');
                Console.Write(LeftPad(extra, 0));
            }   
 
            Console.WriteLine();
        }
#endif
 
        /// <summary>
        /// Check if a primitive only contains white color
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal static bool IsWhitePrimitive(Primitive p)
        {
            GeometryPrimitive gp = p as GeometryPrimitive;
 
            if (gp != null)
            {
                if ((gp.Brush != null) && (gp.Pen == null))
                {
                    return gp.Brush.IsWhite();
                }
 
                if ((gp.Pen != null) && (gp.Brush == null))
                {
                    return gp.Pen.StrokeBrush.IsWhite();
                }
            }
 
            return false;
        }
 
        /// <summary>
        /// Add a primitve to display list
        /// </summary>
        /// <param name="p"></param>
        public void RecordPrimitive(Primitive p)
        {
            if (null == _commands)
            {
                _commands = new List<PrimitiveInfo>();
            }
 
            int index = _commands.Count;
 
            PrimitiveInfo info = new PrimitiveInfo(p);
 
            // Skip empty and totally clipped primitive
 
            bool skip = !Utility.IsRenderVisible(info.bounds) || Utility.Disjoint(p.Clip, info.bounds);
 
            if (!skip)
            {
                if (!m_DisJoint && (index == 0))
                {
                    // Skip white objects in the front
                    skip = IsWhitePrimitive(p);
                }
 
                if (!skip)
                {
                    _commands.Add(info);
                }
            }
 
            if ((p.Clip != null) && Utility.IsRectangle(p.Clip))
            {
                Rect bounds = p.Clip.Bounds;
 
                if ((bounds.Left <= 0) && (bounds.Top <= 0) &&
                    (bounds.Right >= m_width) && (bounds.Bottom >= m_height))
                {
                    // Remove page full clipping
                    p.Clip = null;
                }
                else if ((bounds.Left <= info.bounds.Left) &&
                         (bounds.Top  <= info.bounds.Top) &&
                         (bounds.Right >= info.bounds.Right) &&
                         (bounds.Bottom >= info.bounds.Bottom))
                {
                    // Remove clipping larger than primitive
                    p.Clip = null;
                }
            }
#if DEBUG
            if (skip && (Configuration.Verbose >= 2))
            {
                Console.Write("skip ");
 
                PrintPrimitive(info, index, true);
            }
#endif
        }
 
        public Rect this[int index]
        {
            get
            {
                return (_commands[index]).bounds;
            }
        }
 
        static bool OrderedInsert(List<int> list, int n)
        {
            int pos = list.Count;
 
            // Sort in increasing order, remove duplication
            for (int i = 0; i < pos; i++)
            {
                if (list[i] == n)
                {
                    return false;
                }
 
                if (list[i] > n)
                {
                    pos = i;
                    break;
                }
            }
 
            list.Insert(pos, n);
 
            return true;
        }
 
        public void ReportOverlapping(int one, int two)
        {
            if (one > two)
            {
                int t = one; one = two; two = t;
            }
 
            PrimitiveInfo pi = _commands[one];
 
            if (pi.overlap == null)
            {
                pi.overlap = new List<int>();
            }
 
            if (OrderedInsert(pi.overlap, two))
            {
                PrimitiveInfo qi = _commands[two];
 
                if (!qi.primitive.IsTransparent && !qi.primitive.IsOpaque)
                {
                    pi.overlapHasTransparency ++;
                }
 
                // if (! qi.primitive.IsOpaque) // Remember primitves covered by a primitive having transparency
                {
                    if (qi.underlay == null)
                    {
                        qi.underlay = new List<int>();
                    }
 
                    OrderedInsert(qi.underlay, one);
                }
            }
#if DEBUG
            if (Configuration.Verbose >= 2)
            {
                Console.Write(" <{0} {1}>", one, two);
 
                overlapcount ++;
 
                if (overlapcount >= 10)
                {
                    Console.WriteLine();
                    overlapcount = 0;
                }
            }
#endif
        }
 
#if UNIT_TEST
        internal void Add(double x0, double x1, double y0, double y1)
        {
            if (_commands == null)
            {
                _commands = new ArrayList();
            }
 
            _commands.Add(new PrimitiveInfo(new Rect(x0, y0, x1 - x0, y1 - y0)));
        }
#endif
 
        /// <summary>
        /// Find all primitive bounding box intersections
        /// </summary>
        /// <param name="count">Number of primitives need to be considered. The rest of primitives can be ignored as they are all opaque</param>
        public void CalculateIntersections(int count)
        {
            RectangleIntersection ri = new RectangleIntersection();
 
            ri.CalculateIntersections(this, count);
        }
 
        #endregion
 
        #region Public Properties
        public List<PrimitiveInfo> Commands
        {
            get
            {
                return _commands;
            }
        }
        #endregion
 
        #region Protected Attributes
        protected List<PrimitiveInfo>    _commands; //    = null;
        #endregion
 
    }
} // end of namespace