// External API
        public void RenderImage(ImageProxy image, Rect dest, Geometry clip, Matrix trans, string desp)
        {
            if (image == null)
            {
                return;
            }

            Geometry bounds;
            bool     clipToBounds;

            if (clip == null)
            {
                // no clipping needed, draw everything
                bounds       = Utility.TransformGeometry(new RectangleGeometry(dest), trans);
                clipToBounds = false;
            }
            else
            {
                // clip to provided geometry. it's already in world space
                bounds       = clip;
                clipToBounds = true;
            }

            RenderImage(image, dest, bounds, clipToBounds, 0, trans, desp);
        }
예제 #2
0
        void IProxyDrawingContext.DrawImage(ImageProxy image, Rect dest, Geometry clip, Matrix trans)
        {
            bool empty;

            clip = Utility.Intersect(_clip, Utility.TransformGeometry(clip, _transform), Matrix.Identity, out empty);

            if (empty)
            {
                return;
            }

            ImagePrimitive ip = new ImagePrimitive();

            // Fix bug 1460208: Give each ImagePrimitive its own ImageProxy, since rendering may alter
            // the images.
            ip.Image     = image.Clone();
            ip.DstRect   = dest;
            ip.Clip      = clip;
            ip.Transform = trans * _transform;

            ip.PushOpacity(_opacity, _opacityMask);
            _flattener.AddPrimitive(ip);
        }
예제 #3
0
        void IProxyDrawingContext.DrawImage(ImageProxy image, Rect dest, Geometry clip, Matrix trans)
        {
            if (_costing)
            {
                _cost += image.PixelWidth * image.PixelHeight * 3;

                return;
            }

            // Sometimes clip selects only a small portion of the image. Clip image to reduce amount
            // of data sent to GDI.
            if (clip != null)
            {
                if (!Utility.IsRenderVisible(clip.Bounds))
                {
                    // completely clipped away
                    return;
                }

                // transform clip to image space, taking into account image DPI
                Matrix imageTransform = new Matrix();

                imageTransform.Scale(dest.Width / image.Image.Width, dest.Height / image.Image.Height);
                imageTransform.Translate(dest.X, dest.Y);
                imageTransform.Append(trans);

                imageTransform.Invert();

                Geometry imageClip = Utility.TransformGeometry(clip, imageTransform);

                // Clip the image to clip bounds. ImageProxy.GetClippedImage has no effect if clipping
                // bounds are almost image size.
                Rect clippedImageBounds;

                BitmapSource clippedImageSource = image.GetClippedImage(imageClip.Bounds, out clippedImageBounds);

                if (clippedImageSource == null)
                {
                    // image has been clipped away
                    return;
                }

                ImageProxy clippedImage = new ImageProxy(clippedImageSource);

                // adjust destination rectangle to new clipped image bounds
                double scaleX = dest.Width / image.Image.Width;
                double scaleY = dest.Height / image.Image.Height;

                dest = new Rect(
                    clippedImageBounds.X * scaleX + dest.X,
                    clippedImageBounds.Y * scaleY + dest.Y,
                    clippedImageBounds.Width * scaleX,
                    clippedImageBounds.Height * scaleY
                    );

                image = clippedImage;
            }

            image.BlendOverColor(Colors.White, 1.0, false);

            // BitmapSource img = image.GetImage();

            if (clip != null)
            {
                _dc.PushClip(clip);
            }

            if (!trans.IsIdentity)
            {
                _dc.PushTransform(trans);
            }

#if DEBUG
            _seq++;
            _dc.Comment("-> DrawImage " + _seq);
#endif

            _dc.DrawImage(image.Image, image.Buffer, dest);

#if DEBUG
            _dc.Comment("<- DrawImage " + _seq);

            if (Configuration.Verbose >= 2)
            {
                Console.WriteLine("  DrawImage(" + _comment + ")");
            }
#endif

            if (!trans.IsIdentity)
            {
                _dc.PopTransform();
            }

            if (clip != null)
            {
                _dc.PopClip();
            }
        }
        // Recursive
        // _brush must be in world space
        private void FillGeometry(
            PrimitiveInfo topPI,
            Geometry cur,
            string desp,
            Geometry curAlt,
            string despAlt,
            int start,
            Geometry inter,
            Geometry topBounds
            )
        {
            Primitive p    = topPI.primitive;
            Geometry  diff = Utility.Exclude(cur, topBounds, Matrix.Identity);

            if (diff != null)
            {
                // Render cur [- topBounds] using original brush

                if (_disjoint)
                {
#if DEBUG
                    FillGeometry(diff, Oper(desp, '-', topPI.id), null, null, start + 1);
#else
                    FillGeometry(diff, null, null, null, start + 1);
#endif
                }
                else
                {
                    // Only diff = cur - topBounds need to be rendered. But it may generate more
                    // complicated path and gaps between objects

                    if (curAlt != null)
                    {
#if DEBUG
                        FillGeometry(diff, Oper(desp, '-', topPI.id), curAlt, despAlt, start + 1);
#else
                        FillGeometry(diff, null, curAlt, despAlt, start + 1);
#endif
                    }
                    else
                    {
#if DEBUG
                        FillGeometry(diff, Oper(desp, '-', topPI.id), cur, desp, start + 1);
#else
                        FillGeometry(diff, null, cur, desp, start + 1);
#endif
                    }
                }
            }

            //if (_disjoint || ! p.IsOpaque)
            {
                if (topPI.primitive is ImagePrimitive)
                {
                    // If primitve on the top is ImagePrimitive, change it to DrawImage with blended image.
                    // An alternative will be generating an image brush

                    ImagePrimitive ip = topPI.primitive as ImagePrimitive;

                    bool empty;

                    double imageWidth  = ip.Image.Image.Width;
                    double imageHeight = ip.Image.Image.Height;

                    // Get clip in world space.
                    Geometry clip = Utility.Intersect(inter, Utility.TransformGeometry(new RectangleGeometry(ip.DstRect), ip.Transform), ip.Transform, out empty);

                    if (!empty)
                    {
                        // Get clip bounds in image space.
                        Geometry clipImageSpace = Utility.TransformGeometry(clip, ReverseMap(ip.Transform, ip.DstRect, imageWidth, imageHeight));
                        Rect     drawBounds     = clipImageSpace.Bounds;

                        // Clip image data to the intersection. Resulting draw bounds are in image space.
                        BitmapSource clippedImage = ip.Image.GetClippedImage(drawBounds, out drawBounds);
                        if (clippedImage != null)
                        {
                            // Transform draw bounds back to world space.
                            drawBounds.Scale(ip.DstRect.Width / imageWidth, ip.DstRect.Height / imageHeight);
                            drawBounds.Offset(ip.DstRect.Left, ip.DstRect.Top);

                            ImageProxy image = new ImageProxy(clippedImage);

                            // Blend image with other brush, then render composited image.
                            image.BlendOverBrush(false, _brush, ReverseMap(ip.Transform, drawBounds, image.PixelWidth, image.PixelHeight));

#if DEBUG
                            RenderImage(image, drawBounds, clip, true, start + 1, ip.Transform, Oper(desp, '*', topPI.id));
#else
                            RenderImage(image, drawBounds, clip, true, start + 1, ip.Transform, null);
#endif
                        }
                    }
                }
                else
                {
                    // -- If top primitive opaque, skip the intersection
                    // -- If current primitive is completely covered by an opaque object, skip the intersection
                    if (p.IsOpaque) // && Utility.Covers(topBounds, cur))
                    {
                        cur = null;
                    }
                    else
                    {
                        // Render the intersection using blended brush
                        BrushProxy oldbrush = _brush;

                        _brush = p.BlendBrush(_brush);

#if DEBUG
                        FillGeometry(inter, Oper(desp, '*', topPI.id), null, null, start + 1);
#else
                        FillGeometry(inter, null, null, null, start + 1);
#endif

                        _brush = oldbrush;
                    }
                }

                if (cur != null)
                {
                    bool empty;

                    Geometry geo = Utility.Intersect(cur, _clip, Matrix.Identity, out empty);

                    if (geo != null)
                    {
                        topPI.primitive.Exclude(geo); // exclude cur & _clip

#if DEBUG
                        topPI.id = Oper(topPI.id, '-', Oper(desp, '*', Oper(desp, '.', "c")));
#endif
                    }
                }
            }
        }
        private void RenderImage(
            ImageProxy image,
            Rect dest,
            Geometry bounds,
            bool clipToBounds,
            int start,
            Matrix trans,
            string desp
            )
        {
            PrimitiveInfo topPI;
            Geometry      topBounds;
            Geometry      inter;

            if (FindIntersection(bounds, ref start, out topPI, out topBounds, out inter))
            {
                Primitive p    = topPI.primitive;
                Geometry  diff = Utility.Exclude(bounds, topBounds, trans);

                // DrawImage may modify image
                ImageProxy imageBlend = new ImageProxy(image.GetImage());

                if (diff != null)
                {
                    // Render cur - top
#if DEBUG
                    RenderImage(image, dest, diff, true, start + 1, trans, Oper(desp, '-', topPI.id));
#else
                    RenderImage(image, dest, diff, true, start + 1, trans, null);
#endif
                }

                if (!p.IsTransparent)
                {
#if DEBUG
                    topPI.id = Oper(topPI.id, '-', Oper(desp, '.', "bounds"));
#endif

                    // Render the intersection using blended image
                    p.BlendOverImage(imageBlend, ReverseMap(trans, dest, imageBlend.PixelWidth, imageBlend.PixelHeight));

#if DEBUG
                    RenderImage(imageBlend, dest, inter, true, start + 1, trans, Oper(desp, '*', topPI.id));
#else
                    RenderImage(imageBlend, dest, inter, true, start + 1, trans, null);
#endif
                }

                p.Exclude(bounds);
            }
            else
            {
                Geometry clip = _clip;

                bool empty = false;

                if (clipToBounds)
                {
                    clip = Utility.Intersect(clip, bounds, Matrix.Identity, out empty);
                }

                if (!empty)
                {
                    _dc.Comment(desp);
                    _dc.DrawImage(image, dest, clip, trans);
                }
            }
        }