m

    Mihai Hrincescu

    1 year ago
    Hello everyone ! Is there a reason why we cannot create our own custom brushes by extending Brush()?
    jim

    jim

    1 year ago
    cc @Nader Jawad
    Nader Jawad

    Nader Jawad

    1 year ago
    Yup, Brush is used to configure a "fill" which is either a color or a shader only. Within the DrawScope API we have a very tightly managed Paint object used internally that we update across every draw call. This avoids the Paint management done by devs in the existing android framework as it it allocated and cached in the appropriate location. Question for @Mihai Hrincescu is what did you intend to extend a brush parameter for? Brush is not intended to apply arbitrary paint parameters. In fact Paint is more of an implementation detail of compose and in a majority of cases can be completely avoided. By leveraging this pattern we only have a single Paint object used for an entire composition (1 per AndroidComposeView instance)
    m

    Mihai Hrincescu

    1 year ago
    The use case I wanted was to disable antialiasing when drawing a grid of 1 pixel wide straight lines. I know I can also use the old API's with a paint object I manage myself I was just curios about the reasons behind it.
    Nader Jawad

    Nader Jawad

    1 year ago
    DrawScope gives you access to raw pixel values not density independent pixels so you can ensure you are drawing on a pixel boundary
    Otherwise you can use
    DrawScope.drawIntoCanvas
    to get access to a canvas and you can bring your own Paint object
    m

    Mihai Hrincescu

    1 year ago
    So how would I go about doing that?
    Nader Jawad

    Nader Jawad

    1 year ago
    @Composable
    fun Foo() {
        Canvas(modifier = Modifier.size(100.dp)) {
            drawIntoCanvas { canvas ->
                // Don't recommend, should create and cache this Paint object
                // otherwise it will be allocated on every draw call
                val paint = Paint().apply {
                    style = PaintingStyle.Stroke
                    color = Color.Black
                    isAntiAlias = false
                }
                canvas.drawLine(Offset.Zero, Offset(size.width, 0f), paint)
            }
        }
    }
    Something like this
    But you shouldn't need to enforce antialiasing if you have hold pixel sized strokes and you are always drawing on pixel boundaries
    m

    Mihai Hrincescu

    1 year ago
    I know how to draw lines without the antialiasing using the paint object, I was just wandering if there was a way to do this using the new drawScope api's that is why I was trying to extend the Brush() so I could pass one extra parameter to tell the paint to disable the antialiasing . So rounding the coordinates to nearest Int used to draw the lines would fix this without needing to disable antialiasing?
    Nader Jawad

    Nader Jawad

    1 year ago
    That would be the more ideal approach. Disabiling anti-aliasing leads to visual artifacts that don't look great which is why the default is on. Brush is not intended to be a generic applier of paint params but only configures the color/shader parameters. The others are explicitly configured on each DrawScope API call
    m

    Mihai Hrincescu

    1 year ago
    That clears a lot of confusion for me, and actually makes things simpler. Thx a lot for the answer.
    The fact that all the draw calls take floats really threw me off a little bit there.
    Nader Jawad

    Nader Jawad

    1 year ago
    This is consistent with the android.graphics.Canvas API to drawLines which also takes in floats. It's to ensure you can get visual correctness even when content doesn't land on pixel boundaries and anti-aliasing helps here
    m

    Mihai Hrincescu

    1 year ago
    It all makes sense now, I didn't really noticed that before because I would just disable antialiasing to get the result I wanted and I guess I was just lucky I didn't run into some weird artefacts.