From 4bff818706202378c766e56c63d92f140209db09 Mon Sep 17 00:00:00 2001 From: Denis Koroskin Date: Wed, 10 Feb 2016 11:19:03 -0800 Subject: [PATCH] Workaround for a bug in software Canvas that incorrectly computed clip boundaries (fixes screenshot tests) Summary: Software Canvas uses ints to represents boundaries (because it is backed by Bitmap that has scalar size), whereas Hardware Canvas uses floats to represent boundaries. This results in a bug in Software Canvas where clipping with floats close to or outside of int range results in int overflows and incorrect clipping. To fix the issue, compute the clip boundaries manually instead of using Canvas.clipRect() method (that contains the bug). Reviewed By: sriramramani Differential Revision: D2919509 --- .../java/com/facebook/react/flat/DrawView.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawView.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawView.java index e8b22746f..f51e200d4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawView.java @@ -10,10 +10,12 @@ package com.facebook.react.flat; import android.graphics.Canvas; +import android.graphics.Rect; /* package */ final class DrawView implements DrawCommand { - /* package */ static DrawView INSTANCE = new DrawView(0, 0, 0, 0); + /* package */ static final DrawView INSTANCE = new DrawView(0, 0, 0, 0); + private static final Rect TMP_CLIP_RECT = new Rect(); private final float mClipLeft; private final float mClipTop; @@ -34,8 +36,18 @@ import android.graphics.Canvas; @Override public void draw(FlatViewGroup parent, Canvas canvas) { + // This should not be required, except that there is a bug in Canvas that only shows up in + // screenshot tests where Canvas incorrectly applies clip rect caused by integer overflows + // because software Canvas is actually using ints for bounds, not floats. + canvas.getClipBounds(TMP_CLIP_RECT); + TMP_CLIP_RECT.intersect( + Math.round(mClipLeft), + Math.round(mClipTop), + Math.round(mClipRight), + Math.round(mClipBottom)); + canvas.save(); - canvas.clipRect(mClipLeft, mClipTop, mClipRight, mClipBottom); + canvas.clipRect(TMP_CLIP_RECT); parent.drawNextChild(canvas); canvas.restore(); }