Blurry offset paths when canvas is scaled under hardware acceleration

前端 未结 3 953
情话喂你
情话喂你 2020-12-29 15:48

My application uses a canvas that I scale so that I can specify path points in meters instead of pixels. When I scale the canvas, then draw a line using path.lineTo()<

相关标签:
3条回答
  • 2020-12-29 16:44

    Another way to get around this issue as I've found is to draw the Paths to another Canvas that is backed by a cache bitmap, and then draw that bitmap to the passed Canvas. This eliminates the blurring and offsets in my situation.

    0 讨论(0)
  • 2020-12-29 16:53

    This is a limitation of the hardware accelerated renderer. Paths are rasterized at their native size before transform. In your case, the Path is transformed into a 1x4 texture. That texture is then scaled at draw time. To work around this, scale your Path directly by using Path.transform(Matrix). You can also use scaled coordinates when building the path.

    0 讨论(0)
  • 2020-12-29 16:54

    Thanks to Romain Guy's answer, here is a wrapper for the drawPath() method that produces the same results for hardware acceleration on and off. It only handles the case where the x & y scaling in the existing matrix are the same, and it might not be the most efficient.

    void drawPath(Canvas canvas, Path path, final Paint pen) {
        canvas.save();
    
        // get the current matrix
        Matrix mat = canvas.getMatrix();
    
        // reverse the effects of the current matrix
        Matrix inv = new Matrix();
        mat.invert(inv);
        canvas.concat(inv);
    
        // transform the path
        path.transform(mat);
    
        // get the scale for transforming the Paint
        float[] pts = {0, 0, 1, 0}; // two points 1 unit away from each other
        mat.mapPoints(pts);
        float scale = (float) Math.sqrt(Math.pow(pts[0]-pts[2], 2) + Math.pow(pts[1]-pts[3], 2));
    
        // copy the existing Paint
        Paint pen2 = new Paint();
        pen2.set(pen);
    
        // scale the Paint
        pen2.setStrokeMiter(pen.getStrokeMiter()*scale);
        pen2.setStrokeWidth(pen.getStrokeWidth()*scale);
    
        // draw the path
        canvas.drawPath(path, pen2);
    
        canvas.restore();
    }
    
    0 讨论(0)
提交回复
热议问题