diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-11-28 15:21:52 +0100 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-12-04 23:04:28 +0100 |
commit | b861c1cc383788792a655daf07a07853225cfeb4 (patch) | |
tree | 6fb8286ec398ec75f3010245df8a9cd26a590718 /android/experimental | |
parent | 74eae6786334cdf3a456b52b10fd285e2a589813 (diff) |
android: rearange anc clean-up GeckoLayerClient
Change-Id: I6b4a7f8053adea6d86ee625201eeead188bbadcc
Diffstat (limited to 'android/experimental')
-rw-r--r-- | android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java | 3 | ||||
-rw-r--r-- | android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java | 509 |
2 files changed, 246 insertions, 266 deletions
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java index e9c2877e2445..04b50749a1a0 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java @@ -52,8 +52,7 @@ public class LOKitThread extends Thread { draw(); - RectF rect = new RectF(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); - mLayerClient.setPageRect(rect, rect); + mLayerClient.setPageRect(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); mLayerClient.setViewportMetrics(mLayerClient.getViewportMetrics()); mLayerClient.setForceRedraw(); } diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java index 508fb9f12a9c..99306c5851df 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java @@ -1,40 +1,7 @@ /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Android code. - * - * The Initial Developer of the Original Code is Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009-2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Patrick Walton <pcwalton@mozilla.com> - * Chris Lord <chrislord.net@gmail.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.gfx; @@ -66,13 +33,21 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { private IntSize mScreenSize; private IntSize mWindowSize; private DisplayPortMetrics mDisplayPort; + private DisplayPortMetrics mReturnDisplayPort; private boolean mRecordDrawTimes; - private DrawTimingQueue mDrawTimingQueue; + private final DrawTimingQueue mDrawTimingQueue; private DynamicTileLayer mRootLayer; - /* The Gecko viewport as per the UI thread. Must be touched only on the UI thread. */ + /* The Gecko viewport as per the UI thread. Must be touched only on the UI thread. + * If any events being sent to Gecko that are relative to the Gecko viewport position, + * they must (a) be relative to this viewport, and (b) be sent on the UI thread to + * avoid races. As long as these two conditions are satisfied, and the events being + * sent to Gecko are processed in FIFO order, the events will properly be relative + * to the Gecko viewport position. Note that if Gecko updates its viewport independently, + * we get notified synchronously and also update this on the UI thread. + */ private ImmutableViewportMetrics mGeckoViewport; /* @@ -85,18 +60,20 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { private boolean mPendingViewportAdjust; + private boolean mForceRedraw; + /* The current viewport metrics. - * This is volatile so that we can read and write to it from different threads. - * We avoid synchronization to make getting the viewport metrics from - * the compositor as cheap as possible. The viewport is immutable so - * we don't need to worry about anyone mutating it while we're reading from it. - * Specifically: - * 1) reading mViewportMetrics from any thread is fine without synchronization - * 2) writing to mViewportMetrics requires synchronizing on the layer controller object - * 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in - * case 1 above) you should always frist grab a local copy of the reference, and then use - * that because mViewportMetrics might get reassigned in between reading the different - * fields. */ + * This is volatile so that we can read and write to it from different threads. + * We avoid synchronization to make getting the viewport metrics from + * the compositor as cheap as possible. The viewport is immutable so + * we don't need to worry about anyone mutating it while we're reading from it. + * Specifically: + * 1) reading mViewportMetrics from any thread is fine without synchronization + * 2) writing to mViewportMetrics requires synchronizing on the layer controller object + * 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in + * case 1 above) you should always frist grab a local copy of the reference, and then use + * that because mViewportMetrics might get reassigned in between reading the different + * fields. */ private volatile ImmutableViewportMetrics mViewportMetrics; private ZoomConstraints mZoomConstraints; @@ -104,16 +81,15 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { private boolean mGeckoIsReady; /* The new color for the checkerboard. */ - private int mCheckerboardColor = Color.WHITE; + private int mCheckerboardColor; private boolean mCheckerboardShouldShowChecks; private final PanZoomController mPanZoomController; - private LayerView mView; - private boolean mForceRedraw; - public GeckoLayerClient(Context context) { + // we can fill these in with dummy values because they are always written + // to before being read mContext = context; mScreenSize = new IntSize(0, 0); mWindowSize = new IntSize(0, 0); @@ -125,6 +101,7 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); mViewportMetrics = new ImmutableViewportMetrics(displayMetrics); mZoomConstraints = new ZoomConstraints(false); + mCheckerboardColor = Color.WHITE; mCheckerboardShouldShowChecks = true; mPanZoomController = new PanZoomController(this); @@ -137,8 +114,8 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { public void notifyReady() { mGeckoIsReady = true; - mRootLayer = new DynamicTileLayer(); + mRootLayer = new DynamicTileLayer(); mLayerRenderer = new LayerRenderer(mView); mView.setListener(this); @@ -146,49 +123,50 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { sendResizeEventIfNecessary(true); } - DisplayPortMetrics getDisplayPort() { - return mDisplayPort; - } + /** + * Returns true if this controller is fine with performing a redraw operation or false if it + * would prefer that the action didn't take place. + */ + private boolean getRedrawHint() { + if (mForceRedraw) { + mForceRedraw = false; + return true; + } - public void beginDrawing() { - mRootLayer.beginTransaction(); + if (!mPanZoomController.getRedrawHint()) { + return false; + } + return DisplayPortCalculator.aboutToCheckerboard(mViewportMetrics, mPanZoomController.getVelocityVector(), getDisplayPort()); } - public void endDrawing(ImmutableViewportMetrics viewportMetrics) { - synchronized (this) { - try { - mNewGeckoViewport = viewportMetrics; - updateViewport(true); - mRootLayer.invalidate(); - } finally { - mRootLayer.endTransaction(); - } - } + Layer getRoot() { + return mGeckoIsReady ? mRootLayer : null; } - protected void updateViewport(boolean onlyUpdatePageSize) { - // save and restore the viewport size stored in java; never let the - // JS-side viewport dimensions override the java-side ones because - // java is the One True Source of this information, and allowing JS - // to override can lead to race conditions where this data gets clobbered. - FloatSize viewportSize = getViewportSize(); - mGeckoViewport = mNewGeckoViewport.setViewportSize(viewportSize.width, viewportSize.height); + public LayerView getView() { + return mView; + } - RectF position = mGeckoViewport.getViewport(); - mRootLayer.setPosition(RectUtils.round(position)); - mRootLayer.setResolution(mGeckoViewport.zoomFactor); + public FloatSize getViewportSize() { + return mViewportMetrics.getSize(); + } - if (onlyUpdatePageSize) { - // Don't adjust page size when zooming unless zoom levels are - // approximately equal. - if (FloatUtils.fuzzyEquals(getViewportMetrics().zoomFactor, mGeckoViewport.zoomFactor)) { - setPageRect(mGeckoViewport.getPageRect(), mGeckoViewport.getCssPageRect()); - } - } else { - setViewportMetrics(mGeckoViewport); - abortPanZoomAnimation(); - } + /** + * The view calls this function to indicate that the viewport changed size. It must hold the + * monitor while calling it. + * + * TODO: Refactor this to use an interface. Expose that interface only to the view and not + * to the layer client. That way, the layer client won't be tempted to call this, which might + * result in an infinite loop. + */ + void setViewportSize(FloatSize size) { + mViewportMetrics = mViewportMetrics.setViewportSize(size.width, size.height); + sendResizeEventIfNecessary(true); + } + + public PanZoomController getPanZoomController() { + return mPanZoomController; } /* Informs Gecko that the screen size has changed. */ @@ -214,8 +192,27 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { LOKitShell.sendEvent(event); } - public void viewportSizeChanged() { - sendResizeEventIfNecessary(true); + /** + * Sets the current page rect. You must hold the monitor while calling this. + */ + private void setPageRect(RectF rect, RectF cssRect) { + // Since the "rect" is always just a multiple of "cssRect" we don't need to + // check both; this function assumes that both "rect" and "cssRect" are relative + // the zoom factor in mViewportMetrics. + if (mViewportMetrics.getCssPageRect().equals(cssRect)) + return; + + mViewportMetrics = mViewportMetrics.setPageRect(rect, cssRect); + + // Page size is owned by the layer client, so no need to notify it of + // this change. + + post(new Runnable() { + public void run() { + mPanZoomController.pageRectUpdated(); + mView.requestRender(); + } + }); } void adjustViewport(DisplayPortMetrics displayPort) { @@ -238,21 +235,45 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { } /** - * This function is invoked by Gecko via JNI; be careful when modifying signature. - * The compositor invokes this function whenever it determines that the page size + * Aborts any pan/zoom animation that is currently in progress. + */ + public void abortPanZoomAnimation() { + if (mPanZoomController != null) { + mView.post(new Runnable() { + public void run() { + mPanZoomController.abortAnimation(); + } + }); + } + } + + boolean checkerboardShouldShowChecks() { + return mCheckerboardShouldShowChecks; + } + + int getCheckerboardColor() { + return mCheckerboardColor; + } + + public void setCheckerboardColor(int newColor) { + mCheckerboardColor = newColor; + mView.requestRender(); + } + + public void setZoomConstraints(ZoomConstraints constraints) { + mZoomConstraints = constraints; + } + + /** The compositor invokes this function whenever it determines that the page rect * has changed (based on the information it gets from layout). If setFirstPaintViewport * is invoked on a frame, then this function will not be. For any given frame, this * function will be invoked before syncViewportInfo. */ - public void setPageSize(float zoom, float pageWidth, float pageHeight, float cssPageWidth, float cssPageHeight) { - synchronized (this) { - // adjust the page dimensions to account for differences in zoom - // between the rendered content (which is what the compositor tells us) - // and our zoom level (which may have diverged). - RectF pageRect = new RectF(0.0f, 0.0f, pageWidth, pageHeight); - RectF cssPageRect = new RectF(0.0f, 0.0f, cssPageWidth, cssPageHeight); + public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) { + synchronized (getLock()) { + RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom); float ourZoom = getViewportMetrics().zoomFactor; - setPageRect(RectUtils.scale(pageRect, ourZoom / zoom), cssPageRect); + setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect); // Here the page size of the document has changed, but the document being displayed // is still the same. Therefore, we don't need to send anything to browser.js; any // changes we need to make to the display port will get sent the next time we call @@ -260,189 +281,142 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { } } - public void geometryChanged() { - sendResizeEventIfNecessary(false); - if (getRedrawHint()) { - adjustViewport(null); + DisplayPortMetrics getDisplayPort() { + return mDisplayPort; + } + + public void beginDrawing() { + mRootLayer.beginTransaction(); + + } + + public void endDrawing(ImmutableViewportMetrics viewportMetrics) { + synchronized (this) { + try { + mNewGeckoViewport = viewportMetrics; + updateViewport(true); + mRootLayer.invalidate(); + } finally { + mRootLayer.endTransaction(); + } } } - public ImmutableViewportMetrics getGeckoViewportMetrics() { - return mGeckoViewport; + protected void updateViewport(boolean onlyUpdatePageSize) { + // save and restore the viewport size stored in java; never let the + // JS-side viewport dimensions override the java-side ones because + // java is the One True Source of this information, and allowing JS + // to override can lead to race conditions where this data gets clobbered. + FloatSize viewportSize = getViewportSize(); + mGeckoViewport = mNewGeckoViewport.setViewportSize(viewportSize.width, viewportSize.height); + + RectF position = mGeckoViewport.getViewport(); + mRootLayer.setPosition(RectUtils.round(position)); + mRootLayer.setResolution(mGeckoViewport.zoomFactor); + + if (onlyUpdatePageSize) { + // Don't adjust page size when zooming unless zoom levels are + // approximately equal. + if (FloatUtils.fuzzyEquals(getViewportMetrics().zoomFactor, mGeckoViewport.zoomFactor)) { + setPageRect(mGeckoViewport.getPageRect(), mGeckoViewport.getCssPageRect()); + } + } else { + setViewportMetrics(mGeckoViewport); + abortPanZoomAnimation(); + } } - @Override - public void compositorCreated() { + public void geometryChanged() { + sendResizeEventIfNecessary(false); + if (getRedrawHint()) { + adjustViewport(null); + } } + /** Implementation of LayerView.Listener */ @Override public void renderRequested() { } + /** Implementation of LayerView.Listener */ @Override public void compositionPauseRequested() { } + /** Implementation of LayerView.Listener */ @Override public void compositionResumeRequested(int width, int height) { } + /** Implementation of LayerView.Listener */ @Override public void surfaceChanged(int width, int height) { - renderRequested(); - } - - public void setTileProvider(TileProvider tileProvider) { - mRootLayer.setTileProvider(tileProvider); - } - - public void reevaluateTiles() { - mRootLayer.reevaluateTiles(getViewportMetrics()); - } - - public void clearAndResetlayers() { - mRootLayer.clearAndReset(); - } + setViewportSize(new FloatSize(width, height)); - public void destroy() { - mPanZoomController.destroy(); + // We need to make this call even when the compositor isn't currently + // paused (e.g. during an orientation change), to make the compositor + // aware of the changed surface. + compositionResumeRequested(width, height); + renderRequested(); } - public void setForceRedraw() { - mForceRedraw = true; - notifyLayerClientOfGeometryChange(); + /** Implementation of LayerView.Listener */ + @Override + public void compositorCreated() { } - public LayerView getView() { - return mView; + /** Implementation of PanZoomTarget */ + public ImmutableViewportMetrics getViewportMetrics() { + return mViewportMetrics; } - public Context getContext() { - return mContext; + /** Implementation of PanZoomTarget */ + public ZoomConstraints getZoomConstraints() { + return mZoomConstraints; } - public ImmutableViewportMetrics getViewportMetrics() { - return mViewportMetrics; + /** Implementation of PanZoomTarget */ + public void setAnimationTarget(ImmutableViewportMetrics viewport) { + if (mGeckoIsReady) { + // We know what the final viewport of the animation is going to be, so + // immediately request a draw of that area by setting the display port + // accordingly. This way we should have the content pre-rendered by the + // time the animation is done. + DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(viewport, null); + adjustViewport(displayPort); + } } - /** - * Sets the entire viewport metrics at once. + /** Implementation of PanZoomTarget * You must hold the monitor while calling this. */ public void setViewportMetrics(ImmutableViewportMetrics viewport) { mViewportMetrics = viewport; mView.requestRender(); - notifyLayerClientOfGeometryChange(); - } - - public Object getLock() { - return this; - } - - public FloatSize getViewportSize() { - return mViewportMetrics.getSize(); - } - - /** - * The view calls this function to indicate that the viewport changed size. It must hold the - * monitor while calling it. - * <p/> - * TODO: Refactor this to use an interface. Expose that interface only to the view and not - * to the layer client. That way, the layer client won't be tempted to call this, which might - * result in an infinite loop. - */ - public void setViewportSize(FloatSize size) { - mViewportMetrics = mViewportMetrics.setViewportSize(size.width, size.height); - viewportSizeChanged(); - } - - public PanZoomController getPanZoomController() { - return mPanZoomController; - } - - public GestureDetector.OnGestureListener getGestureListener() { - return mPanZoomController; - } - - public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() { - return mPanZoomController; - } - - public GestureDetector.OnDoubleTapListener getDoubleTapListener() { - return mPanZoomController; - } - - /** - * Sets the current page rect. You must hold the monitor while calling this. - */ - public void setPageRect(RectF rect, RectF cssRect) { - // Since the "rect" is always just a multiple of "cssRect" we don't need to - // check both; this function assumes that both "rect" and "cssRect" are relative - // the zoom factor in mViewportMetrics. - if (mViewportMetrics.getCssPageRect().equals(cssRect)) - return; - - mViewportMetrics = mViewportMetrics.setPageRect(rect, cssRect); - - // Page size is owned by the layer client, so no need to notify it of - // this change. - - mView.post(new Runnable() { - public void run() { - mPanZoomController.pageRectUpdated(); - mView.requestRender(); - } - }); + if (mGeckoIsReady) { + geometryChanged(); + } } - public void setAnimationTarget(ImmutableViewportMetrics viewport) { - // We know what the final viewport of the animation is going to be, so - // immediately request a draw of that area by setting the display port - // accordingly. This way we should have the content pre-rendered by the - // time the animation is done. - DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(viewport, null); - adjustViewport(displayPort); + /** Implementation of PanZoomTarget */ + public void setForceRedraw() { + mForceRedraw = true; + if (mGeckoIsReady) { + geometryChanged(); + } } + /** Implementation of PanZoomTarget */ public boolean post(Runnable action) { return mView.post(action); } - private void notifyLayerClientOfGeometryChange() { - geometryChanged(); - } - - /** - * Aborts any pan/zoom animation that is currently in progress. - */ - public void abortPanZoomAnimation() { - if (mPanZoomController != null) { - mView.post(new Runnable() { - public void run() { - mPanZoomController.abortAnimation(); - } - }); - } - } - - /** - * Returns true if this controller is fine with performing a redraw operation or false if it - * would prefer that the action didn't take place. - */ - public boolean getRedrawHint() { - if (mForceRedraw) { - mForceRedraw = false; - return true; - } - - if (!mPanZoomController.getRedrawHint()) { - return false; - } - - return DisplayPortCalculator.aboutToCheckerboard(mViewportMetrics, mPanZoomController.getVelocityVector(), getDisplayPort()); + /** Implementation of PanZoomTarget */ + public Object getLock() { + return this; } - /** + /** Implementation of PanZoomTarget * Converts a point from layer view coordinates to layer coordinates. In other words, given a * point measured in pixels from the top left corner of the layer view, returns the point in * pixels measured from the last scroll position we sent to Gecko, in CSS pixels. Assuming the @@ -450,10 +424,14 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { * correct. */ public PointF convertViewPointToLayerPoint(PointF viewPoint) { + if (!mGeckoIsReady) { + return null; + } + ImmutableViewportMetrics viewportMetrics = mViewportMetrics; PointF origin = viewportMetrics.getOrigin(); float zoom = viewportMetrics.zoomFactor; - ImmutableViewportMetrics geckoViewport = getGeckoViewportMetrics(); + ImmutableViewportMetrics geckoViewport = mGeckoViewport; PointF geckoOrigin = geckoViewport.getOrigin(); float geckoZoom = geckoViewport.zoomFactor; @@ -470,43 +448,36 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { } /** - * Retrieves whether we should show checkerboard checks or not. + * Sets whether or not the checkerboard should show checkmarks. */ - public boolean checkerboardShouldShowChecks() { - return mCheckerboardShouldShowChecks; + public void setCheckerboardShowChecks(boolean showChecks) { + mCheckerboardShouldShowChecks = showChecks; + mView.requestRender(); } - /** - * Retrieves the color that the checkerboard should be. - */ - public int getCheckerboardColor() { - return mCheckerboardColor; + public ImmutableViewportMetrics getGeckoViewportMetrics() { + return mGeckoViewport; } - /** - * Sets a new color for the checkerboard. - */ - public void setCheckerboardColor(int newColor) { - mCheckerboardColor = newColor; - mView.requestRender(); + public void destroy() { + mPanZoomController.destroy(); } - /** - * Sets whether or not the checkerboard should show checkmarks. - */ - public void setCheckerboardShowChecks(boolean showChecks) { - mCheckerboardShouldShowChecks = showChecks; - mView.requestRender(); + public Context getContext() { + return mContext; } - public ZoomConstraints getZoomConstraints() { - return mZoomConstraints; + public GestureDetector.OnGestureListener getGestureListener() { + return mPanZoomController; } - public void setZoomConstraints(ZoomConstraints constraints) { - mZoomConstraints = constraints; + public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() { + return mPanZoomController; } + public GestureDetector.OnDoubleTapListener getDoubleTapListener() { + return mPanZoomController; + } private class AdjustRunnable implements Runnable { public void run() { mPendingViewportAdjust = false; @@ -514,7 +485,17 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { } } - public Layer getRoot() { - return mRootLayer; + /* Root Layer Access */ + public void setTileProvider(TileProvider tileProvider) { + mRootLayer.setTileProvider(tileProvider); + } + + public void reevaluateTiles() { + mRootLayer.reevaluateTiles(getViewportMetrics()); } + + public void clearAndResetlayers() { + mRootLayer.clearAndReset(); + } + }
\ No newline at end of file |