2

Is it possible to improve the performance of this drawing technique?

 2 years ago
source link: https://www.codesd.com/item/is-it-possible-to-improve-the-performance-of-this-drawing-technique.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Is it possible to improve the performance of this drawing technique?

advertisements

Am currently working on a tool created by a colleague of mine and would like to improve performance. Basically, it's a tool for drawing on screen and uses a combination of Sprites and the Graphics class to draw a line segment every time the mouse is moved when the mouse button is down. Here is the drawing bit:

// on MouseMove
protected function drawLine(e:MouseEvent):void {
        if (currentTool.thickness > 0){
            //pen
            var line:Sprite = new Sprite();

            line.graphics.lineStyle(currentTool.thickness, currentColour);
            line.graphics.moveTo(lastKnownPoint.x, lastKnownPoint.y);
            line.graphics.lineTo(e.localX, e.localY);
            inkLayer.addChild(line);
            lastKnownPoint.x = e.localX;
            lastKnownPoint.y = e.localY;
            e.updateAfterEvent();
        } else {
            //eraser
            var inkChildren:int = inkLayer.numChildren;
            for (var i:uint = inkChildren; i > 0; i--){
                if (toolCursor.hitTestObject(inkLayer.getChildAt(i - 1))){
                    inkLayer.removeChildAt(i - 1);
                }
            }
        }
    }

As you can see, it checks if the line 'thickness' property and draws if it is and erases if it isn't.

I did think of using a technique similar to blitting here where it'd draw to a bitmap but I'm not sure this'd give the performance boost I want or if, indeed, there would be any way to have an eraser function.

Any ideas on a better way to do this? The drawing itself works nicely - this isn't the problem, it's the performance of the subsequent 'drawn' sprites.


I have solved similar problem recently and I could not think of efficient way to implement eraser with vectors. So I made a bitmap to erase drawings from. It works this way: when user selects colored pen, while he holds the left button, draw lines to sprite. When left button is released, sprite is flushed to BitmapData and board is redrawn using this bitmap. When user selects eraser, he draws thick black lines on sprite (they are invisible with alpha = 0). After each movement, affected part of sprite is flushed to BitmapData in erasing mode and this is reflected on board. To support scaling, I made bitmap big and hooked BlurFilter on it. It's not perfect, but works fast enough.

Edit: some code, not tested after cut, but should give the idea:

public class DrawingBoard extends Sprite {
    //...vars declaration
    public function DrawingBoard(width:int, height:int, bitmapWidth:int = 1000, bitmapHeight:int = 1000)
    {
        super();
        scrollRect = new Rectangle(0, 0, width, height);

        downMatrix = new Matrix();
        downMatrix.scale(bitmapWidth / width, bitmapHeight / height);

        upMatrix = new Matrix();
        upMatrix.scale(width / bitmapWidth, height / bitmapHeight);

        bitmap = new BitmapData(bitmapWidth, bitmapHeight, true, 0x00000000);

        //on canvas we draw vector pencils and eraser traces before flush
        canvas = new Sprite();
        addChild(canvas);

        filters = [new BlurFilter(3, 3)];
    }

        //external control api
    public function moveTo(point:Point):void {
        canvas.graphics.moveTo(point.x, point.y);
        var lineWidth:Number = 4 / parent.scaleX;
        canvas.graphics.lineStyle(lineWidth, currentColor, 0.8, false, LineScaleMode.NORMAL);
    }

    public function lineTo(point:Point):void {
        canvas.graphics.lineTo(point.x, point.y);
    }

    public function eraserLineTo(point:Point):void {
        canvas.graphics.lineStyle(eraserSize, 0, 1.0);
        canvas.graphics.lineTo(point.x, point.y);
        flush(BlendMode.ERASE);
        canvas.graphics.moveTo(point.x, point.y);
    }

    public function flush(blendMode:String = null):void {
                    //draw temporary vectors to bitmap
        bitmap.draw(canvas, downMatrix, null, blendMode, null, true);
                    //update board
        var bounds:Rectangle = canvas.getBounds(this);
        with (graphics) {
            beginBitmapFill(bitmap, upMatrix);
            drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
            endFill();
        }
                    //erase temporary vectors
        canvas.graphics.clear();
    }
}




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK