Пример #1
0
        public void DrawGeometry(Brush brush, Pen pen, Geometry geometry)
        {
            // Ignore total transparent primitive
            if (Utility.IsTransparent(_opacity) || ((brush == null) && (pen == null || pen.Brush == null)) || (geometry == null))
            {
                return;
            }

            // Split if having both pen and brush
            if ((brush != null) && (pen != null))
            // if (!Utility.IsOpaque(_opacity) || (_opacityMask != null))
            {
                // Push a canvas to handle geometry with brush + pen properly
                Push(Matrix.Identity, null, 1.0, null, Rect.Empty, false);

                DrawGeometry(brush, null, geometry);
                DrawGeometry(null, pen, geometry);

                Pop();

                return;
            }

            AssertState(DeviceState.PageStarted, DeviceState.NoChange);

            GeometryPrimitive g = new GeometryPrimitive();

            g.Geometry    = geometry;
            g.Clip        = _clip;
            g.Opacity     = _opacity;
            g.OpacityMask = _opacityMask;

            int needBounds = 0; // 1 for fill, 2 for stroke

            if (brush != null)
            {
                // Fix bug 1427695: Need bounds for non-SolidColorBrushes to enable rebuilding Brush from BrushProxy.
                if (!(brush is SolidColorBrush))
                {
                    needBounds |= 1;
                }
            }

            if ((pen != null) && (pen.Brush != null))
            {
                if (!(pen.Brush is SolidColorBrush))
                {
                    needBounds |= 2;
                }
            }

            if (g.OpacityMask != null)
            {
                if (g.OpacityMask.BrushList == null && !(g.OpacityMask.Brush is SolidColorBrush))
                {
                    if (pen != null)
                    {
                        needBounds |= 2;
                    }
                    else
                    {
                        needBounds |= 1;
                    }
                }
            }

            Rect bounds = g.GetRectBounds((needBounds & 1) != 0);

            if (brush != null)
            {
                g.Brush = BrushProxy.CreateBrush(brush, bounds);
            }

            if ((needBounds & 2) != 0)
            {
                bounds = geometry.GetRenderBounds(pen);
            }

            if ((pen != null) && (pen.Brush != null))
            {
                g.Pen = PenProxy.CreatePen(pen, bounds);
            }

            if (g.OpacityMask != null)
            {
                if (!g.OpacityMask.MakeBrushAbsolute(bounds))
                {
                    // Fix bug 1463955: Brush has become empty; replace with transparent brush.
                    g.OpacityMask = BrushProxy.CreateColorBrush(Colors.Transparent);
                }
            }

            // Optimization: Unfold primitive DrawingBrush when possible to avoid rasterizing it.
            Primitive primitive = g.UnfoldDrawingBrush();

            if (primitive != null)
            {
                _root.Children.Add(primitive);
            }
        }
Пример #2
0
        /// <summary>
        /// Optimization: If a transparent primitive is covered underneath immediately by an opaque primitive,
        /// or has nothing underneath, convert it to opaque primitive
        /// </summary>
        /// <param name="commands"></param>
        /// <param name="i"></param>
        private static bool ConvertTransparentOnOpaque(List <PrimitiveInfo> commands, int i)
        {
            PrimitiveInfo pi = commands[i];

            GeometryPrimitive gp = pi.primitive as GeometryPrimitive;

            if (gp != null)
            {
                PrimitiveInfo qi = null;

                if ((pi.underlay != null) && (pi.underlay.Count != 0))
                {
                    qi = commands[pi.underlay[pi.underlay.Count - 1]];
                }

                if ((qi == null) || (qi.primitive.IsOpaque && qi.FullyCovers(pi)))
                {
                    BrushProxy under = BrushProxy.CreateColorBrush(Colors.White);

                    if (qi != null)
                    {
                        GeometryPrimitive qp = qi.primitive as GeometryPrimitive;

                        if (qp != null)
                        {
                            under = qp.Brush;
                        }
                    }

                    if (under != null)
                    {
                        // Blend it with brush underneath
                        BrushProxy blendedBrush    = gp.Brush;
                        BrushProxy blendedPenBrush = gp.Pen == null ? null : gp.Pen.StrokeBrush;

                        if (blendedBrush != null)
                        {
                            blendedBrush = under.BlendBrush(blendedBrush);
                        }
                        else if (blendedPenBrush != null)
                        {
                            blendedPenBrush = under.BlendBrush(blendedPenBrush);
                        }

                        //
                        // Fix bug 1293500:
                        // Allow blending to proceed only if we did not generate pen stroke
                        // brush that is a brush list. Reason: Such a case would have to be
                        // handled during rendering by stroking the object with each brush
                        // in the list. But we're already rendering brushes of underlying
                        // objects, so the optimization is pointless.
                        //
                        bool proceedBlending = true;

                        if (blendedPenBrush != null && blendedPenBrush.BrushList != null)
                        {
                            proceedBlending = false;
                        }

                        if (proceedBlending)
                        {
                            gp.Brush = blendedBrush;
                            if (gp.Pen != null)
                            {
                                gp.Pen.StrokeBrush = blendedPenBrush;
                            }
                        }

                        if (proceedBlending && pi.primitive.IsOpaque)
                        {
#if DEBUG
                            Console.WriteLine("Make {0} opaque", i);
#endif

                            if (pi.underlay != null)
                            {
                                for (int k = 0; k < pi.underlay.Count; k++)
                                {
                                    commands[pi.underlay[k]].overlapHasTransparency--;
                                }
                            }

                            return(true);
                        }
                    }
                }
            }

            return(false);
        }