private void LineAdd_Click(object sender, RoutedEventArgs e)
        {
            if (bitmapArrayWithoutLines == null)
            {
                bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray);
            }
            if (multisamplingForNewLines)
            {
                //bitmapArray.CopyArea(bitmapArrayWithoutLines);

                int scaling = 2;
                bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling);

                var l = new Line(scaling * (int)StartPointX, scaling * (int)StartPointY,
                                 scaling * (int)EndPointX, scaling * (int)EndPointY,
                                 lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness);

                bitmapArrayWithoutLines.DrawLine(l);
                bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling);

                SetBitmapArray(bitmapArrayWithoutLines);
            }
            else
            {
                var l = new Line((int)StartPointX, (int)StartPointY, (int)EndPointX, (int)EndPointY,
                                 lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness);

                Lines.Add(l);
                bitmapArray.DrawLine(l);
            }
        }
        private void DrawingArea_MouseDownOrMove(object sender, MouseEventArgs e)
        {
            if (sender == null || !(sender is Canvas))
            {
                throw new ArgumentException("expected only Canvas", "sender");
            }

            var    canvas = (Canvas)sender;
            double x      = e.GetPosition(canvas).X;
            double y      = e.GetPosition(canvas).Y;

            if (!bitmapArray.IsInBounds((int)x, (int)y))
            {
                return;
            }

            switch (tool)
            {
            case Tools.Filtering:
            {
                // brush border
                if (Shape != BrushShapes.Fill)
                {
                    if (DrawingBrush.Visibility != Visibility.Visible)
                    {
                        DrawingBrush.Visibility = Visibility.Visible;
                    }
                    double half = ((double)sizeOfBrush) / 2;
                    DrawingBrush.Margin = new Thickness(x - half, y - half, 0, 0);
                }

                //System.Text.StringBuilder s = new System.Text.StringBuilder();
                //s.Append("left click at: ").Append(new Point(x, y));
                //s.Append(' ').Append(Filter).Append(' ').Append(Shape);
                //s.Append(' ').Append((int)BrushSize.Value);
                //MessageBox.Show(s.ToString(), sender.GetType().ToString());

                // get filter instance using reflection
                var         typeName = new StringBuilder("GraphicsManipulation.Filters.").Append(Filter).Append("Filter").ToString();
                FilterBrush brush    = (FilterBrush)filtersAssembly.CreateInstance(typeName);

                if (brush is CustomFilter)
                {
                    ((CustomFilter)brush).FilterFunction = latestCustomFilter;
                }

                brush.ApplyAt(bitmapArray, Shape, new Point(x, y), (int)SizeOfBrush, mask);

                if (Shape == BrushShapes.Fill)
                {
                    bitmapArray.RefreshBitmap(Mask.Disabled);
                }
                else
                {
                    bitmapArray.RefreshBitmap(Mask.Rectangle);
                }
            } break;

            case Tools.Line:
            {
                int startX = (int)currentLineStart.X;
                int startY = (int)currentLineStart.Y;
                int endX   = (int)x;
                int endY   = (int)y;

                if (currentLineStart != currentLineEnd)
                {
                    int minX = (int)Math.Min(currentLineStart.X, currentLineEnd.X);
                    int maxX = (int)Math.Max(currentLineStart.X, currentLineEnd.X);
                    int minY = (int)Math.Min(currentLineStart.Y, currentLineEnd.Y);
                    int maxY = (int)Math.Max(currentLineStart.Y, currentLineEnd.Y);
                    bitmapArray.CopyArea(bitmapArrayTemp, minX, minY, maxX, maxY);
                }
                currentLineEnd = new Point(x, y);

                bitmapArray.DrawLine(startX, startY, endX, endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB);
                bitmapArray.RefreshBitmap(Mask.Rectangle);
            } break;
            }
        }
        private void DrawingArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (sender == null || !(sender is Canvas))
            {
                throw new ArgumentException("expected only Canvas", "sender");
            }

            //Status = "ready";

            var canvas = (Canvas)sender;

            if (!keyIsDown)
            {
                return;
            }

            switch (tool)
            {
            case Tools.Filtering:
            {
                ReinitializeMask();
                DrawingBrush.Visibility = Visibility.Hidden;
            } break;

            case Tools.Line:
            {
                double x = e.GetPosition(canvas).X;
                double y = e.GetPosition(canvas).Y;

                int startX = (int)currentLineStart.X;
                int startY = (int)currentLineStart.Y;
                int endX   = (int)x;
                int endY   = (int)y;

                bitmapArray.CopyArea(bitmapArrayTemp);
                if (bitmapArrayWithoutLines == null)
                {
                    bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray);
                }

                if (multisamplingForNewLines)
                {
                    int scaling = 2;
                    bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling);

                    var l = new Line(scaling * startX, scaling * startY, scaling * endX, scaling * endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness);

                    bitmapArrayWithoutLines.DrawLine(l);
                    bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling);

                    SetBitmapArray(bitmapArrayWithoutLines);
                }
                else
                {
                    var l = new Line(startX, startY, endX, endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness);

                    bitmapArray.DrawLine(l);
                    bitmapArray.RefreshBitmap(Mask.Disabled);

                    Lines.Add(l);
                }

                bitmapArrayTemp = null;

                //LineAdd.IsEnabled = true;
                //LineUpdate.IsEnabled = true;
            } break;
            }

            if (canvas.IsMouseCaptured)
            {
                canvas.ReleaseMouseCapture();
            }

            if (keyIsDown)
            {
                keyIsDown = false;
            }
        }