Exemplo n.º 1
0
        public void Pop()
        {
            AssertState(DeviceState.PageStarted, DeviceState.NoChange);

            _opacityMask = _stack.Pop() as BrushProxy;
            _opacity     = (double)_stack.Pop();
            _clip        = _stack.Pop() as Geometry;
            _root        = _stack.Pop() as CanvasPrimitive;
        }
Exemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        public bool StartPage()
        {
            AssertState(DeviceState.DocStarted, DeviceState.PageStarted);

            _page  = new CanvasPrimitive();
            _root  = _page;
            _stack = new Stack();

            _opacity     = 1;
            _opacityMask = null;
            _clip        = null;

            return(true);
        }
Exemplo n.º 3
0
        public void Push(Matrix transform, Geometry clip, double opacity, Brush opacityMask, Rect maskBounds, bool onePrimitive)
        {
            AssertState(DeviceState.PageStarted, DeviceState.NoChange);

            opacity = Utility.NormalizeOpacity(opacity);

            if (!Utility.IsValid(transform))
            {
                // treat as invisible subtree
                opacity   = 0.0;
                transform = Matrix.Identity;
            }

            _stack.Push(_root);
            _stack.Push(_clip);
            _stack.Push(_opacity);
            _stack.Push(_opacityMask);

            bool noTrans = transform.IsIdentity;

            if (onePrimitive && noTrans && (opacityMask == null))
            {
                bool empty;

                _clip        = Utility.Intersect(_clip, clip, Matrix.Identity, out empty);
                _opacity    *= opacity;
                _opacityMask = null;

                if (empty)
                {
                    _opacity = 0;
                }
            }
            else
            {
                CanvasPrimitive c = new CanvasPrimitive();

                if (noTrans)
                {
                    c.Transform = Matrix.Identity;
                }
                else
                {
                    c.Transform = transform;

                    Matrix invertTransform = transform;
                    invertTransform.Invert();

                    _clip = Utility.TransformGeometry(_clip, invertTransform); // transform inherited clip to this level
                }

                bool empty;

                c.Clip    = Utility.Intersect(clip, _clip, Matrix.Identity, out empty); // Combined with inherited attributes
                c.Opacity = opacity * _opacity;

                if (empty)
                {
                    c.Opacity = 0; // Invisible
                }

                if (opacityMask != null)
                {
                    double op;

                    if (Utility.ExtractOpacityMaskOpacity(opacityMask, out op, maskBounds))
                    {
                        c.Opacity = opacity * _opacity * op;
                    }
                    else
                    {
                        c.OpacityMask = BrushProxy.CreateOpacityMaskBrush(opacityMask, maskBounds);
                    }
                }

                _root.Children.Add(c);

                _root = c;

                _clip        = null;
                _opacity     = 1.0;
                _opacityMask = null;
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Flatten the structure of a primitive tree by push clip/transform/opacity onto each leaf node.
        /// Build an index in a DisplayList.
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="clip"></param>
        /// <param name="transform"></param>
        /// <param name="opacity"></param>
        /// <param name="opacityMask"></param>
        public void TreeFlatten(Primitive tree, Geometry clip, Matrix transform, double opacity, BrushProxy opacityMask)
        {
More:
            if (tree == null)
            {
                return;
            }

            Debug.Assert(Utility.IsValid(opacity) && Utility.IsValid(tree.Opacity), "Invalid opacity encountered, should've been normalized in conversion to Primitive");

            // Non-invertible transforms may arise from brush unfolding, where brush content is huge but
            // we need to scale down significantly to fill target region. Allow such transforms.

            CanvasPrimitive canvas = tree as CanvasPrimitive;

            if (canvas != null)
            {
                ArrayList children = canvas.Children;

                // No children, nothing to do
                if ((children == null) || (children.Count == 0))
                {
                    return;
                }

                opacity *= tree.Opacity;

                // transform opacity mask into current primitive space
                if (opacityMask != null)
                {
                    Matrix worldToPrimitiveTransform = tree.Transform;
                    worldToPrimitiveTransform.Invert();

                    opacityMask.ApplyTransform(worldToPrimitiveTransform);
                }

                opacityMask = BrushProxy.BlendBrush(opacityMask, tree.OpacityMask);

                // Skip the subtree if it's transparent enough
                if (Utility.IsTransparent(opacity))
                {
                    return;
                }

                transform = tree.Transform * transform;

                Geometry transclip = Utility.TransformGeometry(tree.Clip, transform);

                bool empty;

                clip = Utility.Intersect(clip, transclip, Matrix.Identity, out empty);

                if (empty)
                {
                    return;
                }

                // For single child, just push transform/clip/opacity onto it.
                if (children.Count == 1)
                {
                    tree = children[0] as Primitive;

                    // Save a recursive call
                    goto More;
                }

                if (Configuration.BlendAlphaWithWhite || Configuration.ForceAlphaOpaque ||
                    (Utility.IsOpaque(opacity) && (opacityMask == null))) // For opaque subtree, just push trasform/clip into it.
                {
                    foreach (Primitive p in children)
                    {
                        TreeFlatten(p, clip, transform, opacity, opacityMask);
                    }
                }
                else
                {
                    // A semi-transparent sub-tree with more than one child
                    Flattener fl = new Flattener(true, _dl.m_width, _dl.m_height);

                    Primitive ntree = tree;
                    ntree.Clip        = null;
                    ntree.Transform   = Matrix.Identity;
                    ntree.Opacity     = 1.0;
                    ntree.OpacityMask = null;

#if DEBUG
                    if (Configuration.Verbose >= 2)
                    {
                        Console.WriteLine("TreeFlatten for subtree");
                    }
#endif

                    if (opacityMask != null)
                    {
                        opacityMask.ApplyTransform(transform);
                    }

                    // Flatten sub-tree structure into a new DisplayList
                    fl.TreeFlatten(ntree, clip, transform, 1.0, null);

                    // Remove alpha in the sub-tree and add to the current display list

#if DEBUG
                    if (Configuration.Verbose >= 2)
                    {
                        Console.WriteLine("end TreeFlatten for subtree");
                        Console.WriteLine("AlphaFlatten for subtree");
                    }
#endif
                    fl.AlphaFlatten(new DisplayListDrawingContext(this, opacity, opacityMask, Matrix.Identity, null), true);

#if DEBUG
                    if (Configuration.Verbose >= 2)
                    {
                        Console.WriteLine("end AlphaFlatten for subtree");
                    }
#endif
                }
            }
            else
            {
                GeometryPrimitive gp = tree as GeometryPrimitive;

                if (gp != null && gp.Brush != null && gp.Pen != null &&
                    (!gp.IsOpaque || !Utility.IsOpaque(opacity)))
                {
                    //
                    // As an optimization we split fill from stroke, however doing so requires
                    // an intermediate canvas to handle translucent fill/stroke, otherwise
                    // the translucent stroke and fill will overlap.
                    //
                    CanvasPrimitive splitCanvas = new CanvasPrimitive();

                    GeometryPrimitive fill   = (GeometryPrimitive)gp;
                    GeometryPrimitive stroke = (GeometryPrimitive)gp.Clone();

                    fill.Pen     = null;
                    stroke.Brush = null;

                    splitCanvas.Children.Add(fill);
                    splitCanvas.Children.Add(stroke);

                    tree = splitCanvas;
                    goto More;
                }

                // Push transform/clip/opacity to leaf node
                tree.Transform = tree.Transform * transform;

                if (tree.Clip == null)
                {
                    tree.Clip = clip;
                }
                else
                {
                    Geometry transclip = Utility.TransformGeometry(tree.Clip, transform);

                    bool empty;

                    tree.Clip = Utility.Intersect(transclip, clip, Matrix.Identity, out empty);

                    if (!empty)
                    {
                        empty = Utility.IsEmpty(tree.Clip, Matrix.Identity);
                    }

                    if (empty)
                    {
                        return;
                    }
                }

                tree.PushOpacity(opacity, opacityMask);

                if (gp != null)
                {
                    // Split fill and stroke into separate primitives if no opacity involved.
                    // Intermediate Canvas not needed due to opaqueness.
                    if ((gp.Brush != null) && (gp.Pen != null))
                    {
                        GeometryPrimitive fill = gp.Clone() as GeometryPrimitive;

                        fill.Pen = null;
                        AddPrimitive(fill);     // Fill only first

                        // Stroke is flattend to fill only when needed
                        gp.Brush = null;
                        AddPrimitive(gp); // Followed by stroke only
                    }
                    else if ((gp.Pen != null) || (gp.Brush != null))
                    {
                        AddPrimitive(gp);
                    }
                }
                else
                {
                    // Record it
                    AddPrimitive(tree);
                }
            }
        }