I am working with Android Canvas , trying to determine how its getClipBounds results are getClipBounds . I understand that Canvas internally saves the Matrix transform, which is updated as I call translate , scale , etc., but trying to replicate the Matrix results that baffled me.
@Override public void onDraw(Canvas canvas) { Rect clipBounds; RectF viewport; canvas.save(); canvas.concat(translationMatrix); //viewportMatrix.preConcat(canvas.getMatrix()); viewportMatrix.set(canvas.getMatrix()); clipBounds = canvas.getClipBounds(); viewport = GetViewport(); Log.d("clipBounds", clipBounds.toString() + " (" + clipBounds.width() + ", " + clipBounds.height() + ")"); Log.d("viewport", viewport.toString() + " (" + viewport.width() + ", " + viewport.height() + ")"); //drawing is done here canvas.restore(); } //viewport code modeled after http://stackoverflow.com/a/17142856/2245528 private RectF GetViewport() { RectF viewport = new RectF(); viewportMatrix.mapRect(viewport, originalViewport); return viewport; } private void Translate(float x, float y) { translationMatrix.postTranslate(x, y); invalidate(); } private void Scale(float scaleFactor, PointF focusPoint) { if (focusPoint == null) { translationMatrix.postScale(scaleFactor, scaleFactor); } //keep the focus point in focus if possible else { translationMatrix.postScale(scaleFactor, scaleFactor, focusPoint.x, focusPoint.y); } invalidate(); } private final Matrix translationMatrix = new Matrix(); private final RectF originalViewport = new RectF(); private final Matrix viewportMatrix = new Matrix();
originalViewport set to 0, 0, canvas.getWidth(), canvas.getHeight() . translate and scale are called from gesture event handlers that work correctly.
Part of me is confused by viewportMatrix . It seems to me that I do not
viewportMatrix.set(canvas.getMatrix());
or
viewportMatrix.preConcat(canvas.getMatrix());
or even a one-time call
viewportMatrix.set(canvas.getMatrix());
at the beginning, followed by side by side translate / scale calls for the two matrices. I even tried completely ignoring the built-in Matrix Canvas and rewriting GetViewport as
//viewport code modeled after http://stackoverflow.com/a/17142856/2245528 private RectF GetViewport() { RectF viewport = new RectF(); translationMatrix.mapRect(viewport, originalViewport); return viewport; }
I can never compare with getClipBounds() , and the discrepancies are pretty serious:
with viewportMatrix.set(canvas.getMatrix) :
clipBounds: Rect (-97, -97 - 602, 452) (699, 549)
viewport: RectF (97.04178, 97.06036, 797.04175, 647.06036) (700.0, 550.0)
with viewportMatrix.preConcat(canvas.getMatrix) :
clipBounds: Rect (-97, -96 - 602, 453) (699, 549)
viewport: RectF (2708.9663, 2722.2754, 3408.9663, 3272.2754) (700.0, 550.0)
with translationMatrix.mapRect :
clipBounds: Rect (-96, -96 - 603, 453) (699, 549)
viewport: RectF (96.73213, 96.85794, 796.7321, 646.8579) (700.0, 550.0).
with a single call to viewportMatrix.preConcat(canvas.getMatrix()) , followed by translate / scale side by side:
clipBounds: Rect (-96, -97 - 603, 452) (699, 549)
viewport: RectF (96.57738, 97.78168, 796.5774, 647.7817) (700.0, 550.0)
with a single call to viewportMatrix.set(canvas.getMatrix()) , followed by translate / scale side by side:
clipBounds: Rect (-96, -96 - 603, 453) (699, 549)
viewport: RectF (96.40051, 96.88153, 796.4005, 646.88153) (700.0, 550.0)
I canβt even check the source of Canvas , because all Matrix code disappears in private calls of its own, the code of which is not displayed.
Why are my GetViewport calls so disconnected and what happens behind the scenes with getClipBounds ?