зеркало из https://github.com/mozilla/gecko-dev.git
Bug 703141 - Reinstate zooming and add CSS zooming after viewport change. r=kats
This patch reinstates pinch-zooming and adds CSS re-scaling so that after zooming, the page is rendered at the scaled resolution and you get clear text. --HG-- rename : mobile/android/base/gfx/IntSize.java => mobile/android/base/gfx/FloatSize.java
This commit is contained in:
Родитель
c5ca0523a3
Коммит
22a6438a2a
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* 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 ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
public final class FloatUtils {
|
||||
public static boolean fuzzyEquals(float a, float b) {
|
||||
return (Math.abs(a - b) < 1e-6);
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.GeckoSoftwareLayerClient;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
|
@ -534,41 +535,24 @@ abstract public class GeckoApp
|
|||
if (getLayerController().getLayerClient() != mSoftwareLayerClient)
|
||||
return;
|
||||
|
||||
IntSize pageSize = getLayerController().getPageSize();
|
||||
Rect visibleArea = getLayerController().getViewport();
|
||||
Point offset = getLayerController().getViewportMetrics().getViewportOffset();
|
||||
ViewportMetrics viewport = mSoftwareLayerClient.getGeckoViewportMetrics();
|
||||
String uri = lastHistoryEntry.mUri;
|
||||
String title = lastHistoryEntry.mTitle;
|
||||
|
||||
SharedPreferences prefs = getPlaceholderPrefs();
|
||||
Editor editor = prefs.edit();
|
||||
|
||||
String uri = lastHistoryEntry.mUri;
|
||||
String title = lastHistoryEntry.mTitle;
|
||||
|
||||
String lastUri = prefs.getString("last-uri", "");
|
||||
String lastTitle = prefs.getString("last-title", uri);
|
||||
|
||||
// see if we can bail.
|
||||
if (uri.equals(lastUri) && title.equals(lastTitle))
|
||||
return;
|
||||
|
||||
editor.putString("last-uri", uri);
|
||||
editor.putString("last-title", title);
|
||||
|
||||
if (pageSize != null) {
|
||||
editor.putInt("page-width", pageSize.width);
|
||||
editor.putInt("page-height", pageSize.height);
|
||||
}
|
||||
|
||||
if (visibleArea != null) {
|
||||
editor.putInt("viewport-left", visibleArea.left);
|
||||
editor.putInt("viewport-top", visibleArea.top);
|
||||
editor.putInt("viewport-right", visibleArea.right);
|
||||
editor.putInt("viewport-bottom", visibleArea.bottom);
|
||||
}
|
||||
|
||||
if (offset != null) {
|
||||
editor.putInt("viewport-offset-x", offset.x);
|
||||
editor.putInt("viewport-offset-y", offset.y);
|
||||
if (viewport != null) {
|
||||
/* XXX Saving this viewport means there may be a slight
|
||||
* discrepancy between what the user sees when shutting down
|
||||
* and what they see when starting up, but it oughtn't be much.
|
||||
*
|
||||
* The alternative is to do a transformation between the two.
|
||||
*/
|
||||
editor.putString("viewport", viewport.toJSON());
|
||||
}
|
||||
|
||||
Log.i(LOGTAG, "Saving:: " + uri + " " + title);
|
||||
|
@ -1067,7 +1051,7 @@ abstract public class GeckoApp
|
|||
|
||||
if (mGeckoLayout.indexOfChild(view) == -1) {
|
||||
lp = new PluginLayoutParams((int) w, (int) h, (int)x, (int)y);
|
||||
lp.repositionFromVisibleRect(mLayerController.getViewport(), 1.0f/*mLayerController.getZoomFactor()*/, true);
|
||||
lp.repositionFromVisibleRect(RectUtils.round(mLayerController.getViewport()), mLayerController.getZoomFactor(), true);
|
||||
|
||||
view.setWillNotDraw(false);
|
||||
if (view instanceof SurfaceView) {
|
||||
|
@ -1082,7 +1066,7 @@ abstract public class GeckoApp
|
|||
} else {
|
||||
lp = (PluginLayoutParams)view.getLayoutParams();
|
||||
lp.reset((int)x, (int)y, (int)w, (int)h);
|
||||
lp.repositionFromVisibleRect(mLayerController.getViewport(), 1.0f/*mLayerController.getZoomFactor()*/, true);
|
||||
lp.repositionFromVisibleRect(RectUtils.round(mLayerController.getViewport()), mLayerController.getZoomFactor(), true);
|
||||
try {
|
||||
mGeckoLayout.updateViewLayout(view, lp);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -1124,7 +1108,7 @@ abstract public class GeckoApp
|
|||
public void repositionPluginViews(boolean resize, boolean setVisible) {
|
||||
for (View view : mPluginViews) {
|
||||
PluginLayoutParams lp = (PluginLayoutParams)view.getLayoutParams();
|
||||
lp.repositionFromVisibleRect(mLayerController.getViewport(), 1.0f/*mLayerController.getZoomFactor()*/, resize);
|
||||
lp.repositionFromVisibleRect(RectUtils.round(mLayerController.getViewport()), mLayerController.getZoomFactor(), resize);
|
||||
|
||||
if (setVisible) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -56,6 +56,7 @@ JAVAFILES = \
|
|||
DoorHanger.java \
|
||||
DoorHangerPopup.java \
|
||||
Favicons.java \
|
||||
FloatUtils.java \
|
||||
GeckoApp.java \
|
||||
GeckoAppShell.java \
|
||||
GeckoConnectivityReceiver.java \
|
||||
|
@ -77,6 +78,7 @@ JAVAFILES = \
|
|||
gfx/CairoGLInfo.java \
|
||||
gfx/CairoImage.java \
|
||||
gfx/CairoUtils.java \
|
||||
gfx/FloatSize.java \
|
||||
gfx/GeckoSoftwareLayerClient.java \
|
||||
gfx/InputConnectionHandler.java \
|
||||
gfx/IntSize.java \
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- 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 ***** */
|
||||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.FloatUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class FloatSize {
|
||||
public final float width, height;
|
||||
|
||||
public FloatSize(FloatSize size) { width = size.width; height = size.height; }
|
||||
public FloatSize(IntSize size) { width = size.width; height = size.height; }
|
||||
public FloatSize(float aWidth, float aHeight) { width = aWidth; height = aHeight; }
|
||||
|
||||
public FloatSize(JSONObject json) {
|
||||
try {
|
||||
width = (float)json.getDouble("width");
|
||||
height = (float)json.getDouble("height");
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return "(" + width + "," + height + ")"; }
|
||||
|
||||
public boolean fuzzyEquals(FloatSize size) {
|
||||
return (FloatUtils.fuzzyEquals(size.width, width) &&
|
||||
FloatUtils.fuzzyEquals(size.height, height));
|
||||
}
|
||||
|
||||
public FloatSize scale(float factor) {
|
||||
return new FloatSize(width * factor, height * factor);
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +43,9 @@ import org.mozilla.gecko.gfx.IntSize;
|
|||
import org.mozilla.gecko.gfx.LayerClient;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.LayerRenderer;
|
||||
import org.mozilla.gecko.gfx.PointUtils;
|
||||
import org.mozilla.gecko.gfx.SingleTileLayer;
|
||||
import org.mozilla.gecko.FloatUtils;
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
|
@ -136,24 +138,32 @@ public class GeckoSoftwareLayerClient extends LayerClient {
|
|||
*/
|
||||
public void endDrawing(int x, int y, int width, int height, String metadata) {
|
||||
try {
|
||||
LayerController controller = getLayerController();
|
||||
if (controller == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
JSONObject metadataObject = new JSONObject(metadata);
|
||||
mGeckoViewport = new ViewportMetrics(metadataObject);
|
||||
|
||||
mTileLayer.setOrigin(mGeckoViewport.getDisplayportOrigin());
|
||||
mTileLayer.setOrigin(PointUtils.round(mGeckoViewport.getDisplayportOrigin()));
|
||||
mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
|
||||
|
||||
// Make sure LayerController metrics changes only happen in the
|
||||
// UI thread.
|
||||
final LayerController controller = getLayerController();
|
||||
|
||||
if (controller != null) {
|
||||
if (mNewContent) {
|
||||
mNewContent = false;
|
||||
controller.setViewportMetrics(mGeckoViewport);
|
||||
} else {
|
||||
controller.setPageSize(mGeckoViewport.getPageSize());
|
||||
}
|
||||
|
||||
controller.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mNewContent) {
|
||||
mNewContent = false;
|
||||
controller.setViewportMetrics(mGeckoViewport);
|
||||
} else {
|
||||
// Don't adjust page size when zooming unless zoom levels are
|
||||
// approximately equal.
|
||||
if (FloatUtils.fuzzyEquals(controller.getZoomFactor(), mGeckoViewport.getZoomFactor()))
|
||||
controller.setPageSize(mGeckoViewport.getPageSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -166,6 +176,11 @@ public class GeckoSoftwareLayerClient extends LayerClient {
|
|||
}
|
||||
}
|
||||
|
||||
public ViewportMetrics getGeckoViewportMetrics() {
|
||||
// Return a copy, as we modify this inside the Gecko thread
|
||||
return new ViewportMetrics(mGeckoViewport);
|
||||
}
|
||||
|
||||
public void geckoLoadedNewContent() {
|
||||
mNewContent = true;
|
||||
}
|
||||
|
@ -236,9 +251,12 @@ public class GeckoSoftwareLayerClient extends LayerClient {
|
|||
}
|
||||
|
||||
private void adjustViewport() {
|
||||
ViewportMetrics viewportMetrics = getLayerController().getViewportMetrics();
|
||||
Point viewportOffset = viewportMetrics.getOptimumViewportOffset();
|
||||
ViewportMetrics viewportMetrics =
|
||||
new ViewportMetrics(getLayerController().getViewportMetrics());
|
||||
|
||||
PointF viewportOffset = viewportMetrics.getOptimumViewportOffset();
|
||||
viewportMetrics.setViewportOffset(viewportOffset);
|
||||
viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
|
||||
|
||||
GeckoEvent event = new GeckoEvent("Viewport:Change", viewportMetrics.toJSON());
|
||||
GeckoAppShell.sendEventToGecko(event);
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.lang.Math;
|
||||
|
||||
public class IntSize {
|
||||
public final int width, height;
|
||||
|
@ -46,6 +48,11 @@ public class IntSize {
|
|||
public IntSize(IntSize size) { width = size.width; height = size.height; }
|
||||
public IntSize(int inWidth, int inHeight) { width = inWidth; height = inHeight; }
|
||||
|
||||
public IntSize(FloatSize size) {
|
||||
width = Math.round(size.width);
|
||||
height = Math.round(size.height);
|
||||
}
|
||||
|
||||
public IntSize(JSONObject json) {
|
||||
try {
|
||||
width = json.getInt("width");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -47,14 +48,17 @@ public abstract class Layer {
|
|||
private boolean mInTransaction;
|
||||
private Point mOrigin;
|
||||
private Point mNewOrigin;
|
||||
private float mResolution;
|
||||
private float mNewResolution;
|
||||
|
||||
public Layer() {
|
||||
mTransactionLock = new ReentrantLock();
|
||||
mOrigin = new Point(0, 0);
|
||||
mResolution = 1.0f;
|
||||
}
|
||||
|
||||
/** Draws the layer. Automatically applies the translation. */
|
||||
public final void draw(GL10 gl) {
|
||||
/** Updates the layer. */
|
||||
public final void update(GL10 gl) {
|
||||
if (mTransactionLock.isHeldByCurrentThread()) {
|
||||
throw new RuntimeException("draw() called while transaction lock held by this " +
|
||||
"thread?!");
|
||||
|
@ -67,9 +71,17 @@ public abstract class Layer {
|
|||
mTransactionLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gl.glPushMatrix();
|
||||
/** Sets the transformation for the layer. */
|
||||
public final void transform(GL10 gl) {
|
||||
gl.glScalef(1.0f / mResolution, 1.0f / mResolution, 1.0f);
|
||||
gl.glTranslatef(mOrigin.x, mOrigin.y, 0.0f);
|
||||
}
|
||||
|
||||
/** Draws the layer. Automatically applies the transformation. */
|
||||
public final void draw(GL10 gl) {
|
||||
gl.glPushMatrix();
|
||||
|
||||
onDraw(gl);
|
||||
|
||||
|
@ -88,6 +100,7 @@ public abstract class Layer {
|
|||
throw new RuntimeException("Nested transactions are not supported");
|
||||
mTransactionLock.lock();
|
||||
mInTransaction = true;
|
||||
mNewResolution = mResolution;
|
||||
}
|
||||
|
||||
/** Call this when you're done modifying the layer. */
|
||||
|
@ -115,6 +128,22 @@ public abstract class Layer {
|
|||
mNewOrigin = newOrigin;
|
||||
}
|
||||
|
||||
/** Returns the current layer's resolution. */
|
||||
public float getResolution() {
|
||||
return mResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the layer resolution. This value is used to determine how many pixels per
|
||||
* device pixel this layer was rendered at. This will be reflected by scaling by
|
||||
* the reciprocal of the resolution in the layer's transform() function.
|
||||
* Only valid inside a transaction. */
|
||||
public void setResolution(float newResolution) {
|
||||
if (!mInTransaction)
|
||||
throw new RuntimeException("setResolution() is only valid inside a transaction");
|
||||
mNewResolution = newResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses implement this method to perform drawing.
|
||||
*
|
||||
|
@ -132,6 +161,7 @@ public abstract class Layer {
|
|||
mOrigin = mNewOrigin;
|
||||
mNewOrigin = null;
|
||||
}
|
||||
mResolution = mNewResolution;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,19 +110,26 @@ public class LayerController {
|
|||
public Context getContext() { return mContext; }
|
||||
public ViewportMetrics getViewportMetrics() { return mViewportMetrics; }
|
||||
|
||||
public Rect getViewport() {
|
||||
public RectF getViewport() {
|
||||
return mViewportMetrics.getViewport();
|
||||
}
|
||||
|
||||
public IntSize getViewportSize() {
|
||||
Rect viewport = getViewport();
|
||||
return new IntSize(viewport.width(), viewport.height());
|
||||
public FloatSize getViewportSize() {
|
||||
return mViewportMetrics.getSize();
|
||||
}
|
||||
|
||||
public IntSize getPageSize() {
|
||||
public FloatSize getPageSize() {
|
||||
return mViewportMetrics.getPageSize();
|
||||
}
|
||||
|
||||
public PointF getOrigin() {
|
||||
return mViewportMetrics.getOrigin();
|
||||
}
|
||||
|
||||
public float getZoomFactor() {
|
||||
return mViewportMetrics.getZoomFactor();
|
||||
}
|
||||
|
||||
public Bitmap getCheckerboardPattern() { return getDrawable("checkerboard"); }
|
||||
public Bitmap getShadowPattern() { return getDrawable("shadow"); }
|
||||
|
||||
|
@ -144,7 +151,7 @@ public class LayerController {
|
|||
* 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(IntSize size) {
|
||||
public void setViewportSize(FloatSize size) {
|
||||
mViewportMetrics.setSize(size);
|
||||
|
||||
notifyLayerClientOfGeometryChange();
|
||||
|
@ -152,21 +159,28 @@ public class LayerController {
|
|||
}
|
||||
|
||||
public void scrollTo(PointF point) {
|
||||
mViewportMetrics.setOrigin(new Point(Math.round(point.x),
|
||||
Math.round(point.y)));
|
||||
mViewportMetrics.setOrigin(point);
|
||||
notifyLayerClientOfGeometryChange();
|
||||
mPanZoomController.geometryChanged();
|
||||
}
|
||||
|
||||
public void scrollBy(PointF point) {
|
||||
PointF origin = mViewportMetrics.getOrigin();
|
||||
origin.offset(point.x, point.y);
|
||||
mViewportMetrics.setOrigin(origin);
|
||||
|
||||
notifyLayerClientOfGeometryChange();
|
||||
mPanZoomController.geometryChanged();
|
||||
}
|
||||
|
||||
public void setViewport(Rect viewport) {
|
||||
public void setViewport(RectF viewport) {
|
||||
mViewportMetrics.setViewport(viewport);
|
||||
notifyLayerClientOfGeometryChange();
|
||||
mPanZoomController.geometryChanged();
|
||||
}
|
||||
|
||||
public void setPageSize(IntSize size) {
|
||||
if (mViewportMetrics.getPageSize().equals(size))
|
||||
public void setPageSize(FloatSize size) {
|
||||
if (mViewportMetrics.getPageSize().fuzzyEquals(size))
|
||||
return;
|
||||
|
||||
mViewportMetrics.setPageSize(size);
|
||||
|
@ -184,6 +198,14 @@ public class LayerController {
|
|||
mPanZoomController.geometryChanged();
|
||||
}
|
||||
|
||||
public void scaleTo(float zoomFactor, PointF focus) {
|
||||
mViewportMetrics.scaleTo(zoomFactor, focus);
|
||||
|
||||
// We assume the zoom level will only be modified by the
|
||||
// PanZoomController, so no need to notify it of this change.
|
||||
notifyLayerClientOfGeometryChange();
|
||||
}
|
||||
|
||||
public boolean post(Runnable action) { return mView.post(action); }
|
||||
|
||||
public void setOnTouchListener(OnTouchListener onTouchListener) {
|
||||
|
@ -204,7 +226,7 @@ public class LayerController {
|
|||
* would prefer that the action didn't take place.
|
||||
*/
|
||||
public boolean getRedrawHint() {
|
||||
return aboutToCheckerboard();
|
||||
return true;//aboutToCheckerboard();
|
||||
}
|
||||
|
||||
private RectF getTileRect() {
|
||||
|
@ -231,7 +253,8 @@ public class LayerController {
|
|||
return null;
|
||||
|
||||
// Undo the transforms.
|
||||
PointF newPoint = new PointF(mViewportMetrics.getOrigin());
|
||||
PointF origin = mViewportMetrics.getOrigin();
|
||||
PointF newPoint = new PointF(origin.x, origin.y);
|
||||
newPoint.offset(viewPoint.x, viewPoint.y);
|
||||
|
||||
Point rootOrigin = mRootLayer.getOrigin();
|
||||
|
|
|
@ -48,6 +48,8 @@ import org.mozilla.gecko.gfx.TextureReaper;
|
|||
import org.mozilla.gecko.gfx.TextLayer;
|
||||
import org.mozilla.gecko.gfx.TileLayer;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.opengl.GLSurfaceView;
|
||||
|
@ -108,38 +110,48 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
|||
TextureReaper.get().reap(gl);
|
||||
|
||||
LayerController controller = mView.getController();
|
||||
Rect pageRect = getPageRect();
|
||||
Layer rootLayer = controller.getRoot();
|
||||
|
||||
/* Update layers */
|
||||
if (rootLayer != null) rootLayer.update(gl);
|
||||
mShadowLayer.update(gl);
|
||||
mCheckerboardLayer.update(gl);
|
||||
mFPSLayer.update(gl);
|
||||
mVertScrollLayer.update(gl);
|
||||
mHorizScrollLayer.update(gl);
|
||||
|
||||
/* Draw the background. */
|
||||
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Draw the drop shadow. */
|
||||
setupPageTransform(gl);
|
||||
setupPageTransform(gl, false);
|
||||
mShadowLayer.draw(gl);
|
||||
|
||||
/* Draw the checkerboard. */
|
||||
Rect clampedPageRect = clampToScreen(pageRect);
|
||||
IntSize screenSize = controller.getViewportSize();
|
||||
Rect pageRect = getPageRect();
|
||||
Rect scissorRect = transformToScissorRect(pageRect);
|
||||
gl.glEnable(GL10.GL_SCISSOR_TEST);
|
||||
gl.glScissor(clampedPageRect.left, screenSize.height - clampedPageRect.bottom,
|
||||
clampedPageRect.width(), clampedPageRect.height());
|
||||
gl.glScissor(scissorRect.left, scissorRect.top,
|
||||
scissorRect.width(), scissorRect.height());
|
||||
|
||||
gl.glLoadIdentity();
|
||||
mCheckerboardLayer.draw(gl);
|
||||
|
||||
/* Draw the layer the client added to us. */
|
||||
setupPageTransform(gl);
|
||||
|
||||
Layer rootLayer = controller.getRoot();
|
||||
if (rootLayer != null)
|
||||
if (rootLayer != null) {
|
||||
gl.glLoadIdentity();
|
||||
setupPageTransform(gl, true);
|
||||
rootLayer.transform(gl);
|
||||
rootLayer.draw(gl);
|
||||
}
|
||||
|
||||
gl.glDisable(GL10.GL_SCISSOR_TEST);
|
||||
|
||||
gl.glEnable(GL10.GL_BLEND);
|
||||
|
||||
/* Draw the vertical scrollbar */
|
||||
IntSize screenSize = new IntSize(controller.getViewportSize());
|
||||
if (pageRect.height() > screenSize.height) {
|
||||
mVertScrollLayer.drawVertical(gl, screenSize, pageRect);
|
||||
}
|
||||
|
@ -156,38 +168,41 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
|||
gl.glDisable(GL10.GL_BLEND);
|
||||
}
|
||||
|
||||
private void setupPageTransform(GL10 gl) {
|
||||
private void setupPageTransform(GL10 gl, boolean scale) {
|
||||
LayerController controller = mView.getController();
|
||||
Rect viewport = controller.getViewport();
|
||||
//float zoomFactor = controller.getZoomFactor();
|
||||
|
||||
gl.glLoadIdentity();
|
||||
//gl.glScalef(zoomFactor, zoomFactor, 1.0f);
|
||||
gl.glTranslatef(-viewport.left, -viewport.top, 0.0f);
|
||||
PointF origin = controller.getOrigin();
|
||||
gl.glTranslatef(-origin.x, -origin.y, 0.0f);
|
||||
|
||||
if (scale) {
|
||||
float zoomFactor = controller.getZoomFactor();
|
||||
gl.glScalef(zoomFactor, zoomFactor, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private Rect getPageRect() {
|
||||
LayerController controller = mView.getController();
|
||||
float zoomFactor = 1.0f;//controller.getZoomFactor();
|
||||
Rect viewport = controller.getViewport();
|
||||
IntSize pageSize = controller.getPageSize();
|
||||
|
||||
int x = (int)Math.round(-zoomFactor * viewport.left);
|
||||
int y = (int)Math.round(-zoomFactor * viewport.top);
|
||||
return new Rect(x, y,
|
||||
x + (int)Math.round(zoomFactor * pageSize.width),
|
||||
y + (int)Math.round(zoomFactor * pageSize.height));
|
||||
Point origin = PointUtils.round(controller.getOrigin());
|
||||
IntSize pageSize = new IntSize(controller.getPageSize());
|
||||
|
||||
origin.negate();
|
||||
|
||||
return new Rect(origin.x, origin.y,
|
||||
origin.x + pageSize.width, origin.y + pageSize.height);
|
||||
}
|
||||
|
||||
private Rect clampToScreen(Rect rect) {
|
||||
private Rect transformToScissorRect(Rect rect) {
|
||||
LayerController controller = mView.getController();
|
||||
IntSize screenSize = controller.getViewportSize();
|
||||
IntSize screenSize = new IntSize(controller.getViewportSize());
|
||||
|
||||
int left = Math.max(0, rect.left);
|
||||
int top = Math.max(0, rect.top);
|
||||
int right = Math.min(screenSize.width, rect.right);
|
||||
int bottom = Math.min(screenSize.height, rect.bottom);
|
||||
return new Rect(left, top, right, bottom);
|
||||
|
||||
return new Rect(left, screenSize.height - bottom, right,
|
||||
(screenSize.height - bottom) + (bottom - top));
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, final int width, final int height) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import android.content.Context;
|
||||
|
@ -91,7 +92,7 @@ public class LayerView extends GLSurfaceView {
|
|||
|
||||
/** The LayerRenderer calls this to indicate that the window has changed size. */
|
||||
public void setViewportSize(IntSize size) {
|
||||
mController.setViewportSize(size);
|
||||
mController.setViewportSize(new FloatSize(size));
|
||||
}
|
||||
|
||||
public void setInputConnectionHandler(InputConnectionHandler handler) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
|
@ -50,7 +51,7 @@ public class NinePatchTileLayer extends TileLayer {
|
|||
private FloatBuffer mSideTexCoordBuffer, mSideVertexBuffer;
|
||||
private FloatBuffer mTopTexCoordBuffer, mTopVertexBuffer;
|
||||
private LayerController mLayerController;
|
||||
private IntSize mPageSize;
|
||||
private FloatSize mPageSize;
|
||||
|
||||
private static final int PATCH_SIZE = 16;
|
||||
private static final int TEXTURE_SIZE = 48;
|
||||
|
@ -91,7 +92,7 @@ public class NinePatchTileLayer extends TileLayer {
|
|||
public NinePatchTileLayer(LayerController layerController, CairoImage image) {
|
||||
super(false, image);
|
||||
|
||||
mPageSize = new IntSize(1, 1);
|
||||
mPageSize = new FloatSize(1.0f, 1.0f);
|
||||
mLayerController = layerController;
|
||||
|
||||
mSideTexCoordBuffer = createBuffer(SIDE_TEX_COORDS);
|
||||
|
@ -125,8 +126,8 @@ public class NinePatchTileLayer extends TileLayer {
|
|||
|
||||
@Override
|
||||
protected void onTileDraw(GL10 gl) {
|
||||
IntSize pageSize = mLayerController.getPageSize();
|
||||
if (!pageSize.equals(mPageSize)) {
|
||||
FloatSize pageSize = mLayerController.getPageSize();
|
||||
if (!pageSize.fuzzyEquals(mPageSize)) {
|
||||
mPageSize = pageSize;
|
||||
recreateVertexBuffers();
|
||||
}
|
||||
|
|
|
@ -39,19 +39,22 @@ package org.mozilla.gecko.gfx;
|
|||
|
||||
import org.mozilla.gecko.gfx.BufferedCairoImage;
|
||||
import org.mozilla.gecko.gfx.CairoUtils;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.LayerClient;
|
||||
import org.mozilla.gecko.gfx.PointUtils;
|
||||
import org.mozilla.gecko.gfx.SingleTileLayer;
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.io.File;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
@ -60,8 +63,11 @@ import java.nio.ByteBuffer;
|
|||
* is up, then we hand off control to it.
|
||||
*/
|
||||
public class PlaceholderLayerClient extends LayerClient {
|
||||
private static final String LOGTAG = "PlaceholderLayerClient";
|
||||
|
||||
private Context mContext;
|
||||
private ViewportMetrics mViewport;
|
||||
private boolean mViewportUnknown;
|
||||
private int mWidth, mHeight, mFormat;
|
||||
private ByteBuffer mBuffer;
|
||||
private FetchImageTask mTask;
|
||||
|
@ -69,19 +75,19 @@ public class PlaceholderLayerClient extends LayerClient {
|
|||
private PlaceholderLayerClient(Context context) {
|
||||
mContext = context;
|
||||
SharedPreferences prefs = GeckoApp.mAppContext.getPlaceholderPrefs();
|
||||
IntSize pageSize = new IntSize(prefs.getInt("page-width", 995),
|
||||
prefs.getInt("page-height", 1250));
|
||||
Rect viewport = new Rect(prefs.getInt("viewport-left", 0),
|
||||
prefs.getInt("viewport-top", 0),
|
||||
prefs.getInt("viewport-right", 1),
|
||||
prefs.getInt("viewport-bottom", 1));
|
||||
Point offset = new Point(prefs.getInt("viewport-offset-x", 0),
|
||||
prefs.getInt("viewport-offset-y", 0));
|
||||
|
||||
mViewport = new ViewportMetrics();
|
||||
mViewport.setPageSize(pageSize);
|
||||
mViewport.setViewport(viewport);
|
||||
mViewport.setViewportOffset(offset);
|
||||
mViewportUnknown = true;
|
||||
if (prefs.contains("viewport")) {
|
||||
try {
|
||||
JSONObject viewportObject = new JSONObject(prefs.getString("viewport", null));
|
||||
mViewport = new ViewportMetrics(viewportObject);
|
||||
mViewportUnknown = false;
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error parsing saved viewport!");
|
||||
mViewport = new ViewportMetrics();
|
||||
}
|
||||
} else {
|
||||
mViewport = new ViewportMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
public static PlaceholderLayerClient createInstance(Context context) {
|
||||
|
@ -116,6 +122,13 @@ public class PlaceholderLayerClient extends LayerClient {
|
|||
mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * bpp);
|
||||
|
||||
bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
|
||||
|
||||
if (mViewportUnknown) {
|
||||
mViewport.setPageSize(new FloatSize(mWidth, mHeight));
|
||||
if (getLayerController() != null)
|
||||
getLayerController().setPageSize(mViewport.getPageSize());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -125,7 +138,7 @@ public class PlaceholderLayerClient extends LayerClient {
|
|||
SingleTileLayer tileLayer = new SingleTileLayer(image);
|
||||
|
||||
tileLayer.beginTransaction();
|
||||
tileLayer.setOrigin(mViewport.getDisplayportOrigin());
|
||||
tileLayer.setOrigin(PointUtils.round(mViewport.getDisplayportOrigin()));
|
||||
tileLayer.endTransaction();
|
||||
|
||||
getLayerController().setRoot(tileLayer);
|
||||
|
@ -141,6 +154,8 @@ public class PlaceholderLayerClient extends LayerClient {
|
|||
public void setLayerController(LayerController layerController) {
|
||||
super.setLayerController(layerController);
|
||||
|
||||
if (mViewportUnknown)
|
||||
mViewport.setViewport(layerController.getViewport());
|
||||
layerController.setViewportMetrics(mViewport);
|
||||
|
||||
BufferedCairoImage image = new BufferedCairoImage(mBuffer, mWidth, mHeight, mFormat);
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import java.lang.Math;
|
||||
|
||||
public final class PointUtils {
|
||||
public static PointF add(PointF one, PointF two) {
|
||||
|
@ -51,5 +53,9 @@ public final class PointUtils {
|
|||
public static PointF scale(PointF point, float factor) {
|
||||
return new PointF(point.x * factor, point.y * factor);
|
||||
}
|
||||
|
||||
public static Point round(PointF point) {
|
||||
return new Point(Math.round(point.x), Math.round(point.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,4 +88,9 @@ public final class RectUtils {
|
|||
x + (rect.width() * scale),
|
||||
y + (rect.height() * scale));
|
||||
}
|
||||
|
||||
public static Rect round(RectF rect) {
|
||||
return new Rect(Math.round(rect.left), Math.round(rect.top),
|
||||
Math.round(rect.right), Math.round(rect.bottom));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,9 +39,12 @@
|
|||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import android.graphics.RectF;
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.RectUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import android.util.Log;
|
||||
|
@ -51,51 +54,57 @@ import android.util.Log;
|
|||
* the page viewport for the Gecko layer client to use.
|
||||
*/
|
||||
public class ViewportMetrics {
|
||||
private IntSize mPageSize;
|
||||
private Rect mViewportRect;
|
||||
private Point mViewportOffset;
|
||||
private FloatSize mPageSize;
|
||||
private RectF mViewportRect;
|
||||
private PointF mViewportOffset;
|
||||
private float mZoomFactor;
|
||||
|
||||
public ViewportMetrics() {
|
||||
mPageSize = new IntSize(LayerController.TILE_WIDTH,
|
||||
LayerController.TILE_HEIGHT);
|
||||
mViewportRect = new Rect(0, 0, 1, 1);
|
||||
mViewportOffset = new Point(0, 0);
|
||||
mPageSize = new FloatSize(LayerController.TILE_WIDTH,
|
||||
LayerController.TILE_HEIGHT);
|
||||
mViewportRect = new RectF(0, 0, 1, 1);
|
||||
mViewportOffset = new PointF(0, 0);
|
||||
mZoomFactor = 1.0f;
|
||||
}
|
||||
|
||||
public ViewportMetrics(ViewportMetrics viewport) {
|
||||
mPageSize = new IntSize(viewport.getPageSize());
|
||||
mViewportRect = new Rect(viewport.getViewport());
|
||||
mViewportOffset = new Point(viewport.getViewportOffset());
|
||||
mPageSize = new FloatSize(viewport.getPageSize());
|
||||
mViewportRect = new RectF(viewport.getViewport());
|
||||
PointF offset = viewport.getViewportOffset();
|
||||
mViewportOffset = new PointF(offset.x, offset.y);
|
||||
mZoomFactor = viewport.getZoomFactor();
|
||||
}
|
||||
|
||||
public ViewportMetrics(JSONObject json) throws JSONException {
|
||||
int x = json.getInt("x");
|
||||
int y = json.getInt("y");
|
||||
int width = json.getInt("width");
|
||||
int height = json.getInt("height");
|
||||
int pageWidth = json.getInt("pageWidth");
|
||||
int pageHeight = json.getInt("pageHeight");
|
||||
int offsetX = json.getInt("offsetX");
|
||||
int offsetY = json.getInt("offsetY");
|
||||
float x = (float)json.getDouble("x");
|
||||
float y = (float)json.getDouble("y");
|
||||
float width = (float)json.getDouble("width");
|
||||
float height = (float)json.getDouble("height");
|
||||
float pageWidth = (float)json.getDouble("pageWidth");
|
||||
float pageHeight = (float)json.getDouble("pageHeight");
|
||||
float offsetX = (float)json.getDouble("offsetX");
|
||||
float offsetY = (float)json.getDouble("offsetY");
|
||||
float zoom = (float)json.getDouble("zoom");
|
||||
|
||||
mPageSize = new IntSize(pageWidth, pageHeight);
|
||||
mViewportRect = new Rect(x, y, x + width, y + height);
|
||||
mViewportOffset = new Point(offsetX, offsetY);
|
||||
mPageSize = new FloatSize(pageWidth, pageHeight);
|
||||
mViewportRect = new RectF(x, y, x + width, y + height);
|
||||
mViewportOffset = new PointF(offsetX, offsetY);
|
||||
mZoomFactor = zoom;
|
||||
}
|
||||
|
||||
public Point getOptimumViewportOffset() {
|
||||
public PointF getOptimumViewportOffset() {
|
||||
// XXX We currently always position the viewport in the centre of the
|
||||
// displayport, but we might want to optimise this during panning
|
||||
// to minimise checkerboarding.
|
||||
Point optimumOffset =
|
||||
new Point((LayerController.TILE_WIDTH - mViewportRect.width()) / 2,
|
||||
(LayerController.TILE_HEIGHT - mViewportRect.height()) / 2);
|
||||
new Point((int)Math.round((LayerController.TILE_WIDTH - mViewportRect.width()) / 2),
|
||||
(int)Math.round((LayerController.TILE_HEIGHT - mViewportRect.height()) / 2));
|
||||
|
||||
/* XXX Until bug #524925 is fixed, changing the viewport origin will
|
||||
* probably cause things to be slower than just having a smaller usable
|
||||
* displayport.
|
||||
*/
|
||||
Rect viewport = getClampedViewport();
|
||||
Rect viewport = RectUtils.round(getClampedViewport());
|
||||
|
||||
// Make sure this offset won't cause wasted pixels in the displayport
|
||||
// (i.e. make sure the resultant displayport intersects with the page
|
||||
|
@ -110,29 +119,29 @@ public class ViewportMetrics {
|
|||
else if (optimumOffset.y + viewport.bottom > mPageSize.height)
|
||||
optimumOffset.y -= (mPageSize.height - (optimumOffset.y + viewport.bottom));
|
||||
|
||||
return optimumOffset;
|
||||
return new PointF(optimumOffset);
|
||||
}
|
||||
|
||||
public Point getOrigin() {
|
||||
return new Point(mViewportRect.left, mViewportRect.top);
|
||||
public PointF getOrigin() {
|
||||
return new PointF(mViewportRect.left, mViewportRect.top);
|
||||
}
|
||||
|
||||
public Point getDisplayportOrigin() {
|
||||
return new Point(mViewportRect.left - mViewportOffset.x,
|
||||
mViewportRect.top - mViewportOffset.y);
|
||||
public PointF getDisplayportOrigin() {
|
||||
return new PointF(mViewportRect.left - mViewportOffset.x,
|
||||
mViewportRect.top - mViewportOffset.y);
|
||||
}
|
||||
|
||||
public IntSize getSize() {
|
||||
return new IntSize(mViewportRect.width(), mViewportRect.height());
|
||||
public FloatSize getSize() {
|
||||
return new FloatSize(mViewportRect.width(), mViewportRect.height());
|
||||
}
|
||||
|
||||
public Rect getViewport() {
|
||||
public RectF getViewport() {
|
||||
return mViewportRect;
|
||||
}
|
||||
|
||||
/** Returns the viewport rectangle, clamped within the page-size. */
|
||||
public Rect getClampedViewport() {
|
||||
Rect clampedViewport = new Rect(mViewportRect);
|
||||
public RectF getClampedViewport() {
|
||||
RectF clampedViewport = new RectF(mViewportRect);
|
||||
|
||||
// While the viewport size ought to never exceed the page size, we
|
||||
// do the clamping in this order to make sure that the origin is
|
||||
|
@ -150,41 +159,61 @@ public class ViewportMetrics {
|
|||
return clampedViewport;
|
||||
}
|
||||
|
||||
public Point getViewportOffset() {
|
||||
public PointF getViewportOffset() {
|
||||
return mViewportOffset;
|
||||
}
|
||||
|
||||
public IntSize getPageSize() {
|
||||
public FloatSize getPageSize() {
|
||||
return mPageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(IntSize pageSize) {
|
||||
public float getZoomFactor() {
|
||||
return mZoomFactor;
|
||||
}
|
||||
|
||||
public void setPageSize(FloatSize pageSize) {
|
||||
mPageSize = pageSize;
|
||||
}
|
||||
|
||||
public void setViewport(Rect viewport) {
|
||||
public void setViewport(RectF viewport) {
|
||||
mViewportRect = viewport;
|
||||
}
|
||||
|
||||
public void setOrigin(Point origin) {
|
||||
public void setOrigin(PointF origin) {
|
||||
mViewportRect.set(origin.x, origin.y,
|
||||
origin.x + mViewportRect.width(),
|
||||
origin.y + mViewportRect.height());
|
||||
}
|
||||
|
||||
public void setSize(IntSize size) {
|
||||
public void setSize(FloatSize size) {
|
||||
mViewportRect.right = mViewportRect.left + size.width;
|
||||
mViewportRect.bottom = mViewportRect.top + size.height;
|
||||
}
|
||||
|
||||
public void setViewportOffset(Point offset) {
|
||||
public void setViewportOffset(PointF offset) {
|
||||
mViewportOffset = offset;
|
||||
}
|
||||
|
||||
public boolean equals(ViewportMetrics viewport) {
|
||||
return mViewportRect.equals(viewport.getViewport()) &&
|
||||
mPageSize.equals(viewport.getPageSize()) &&
|
||||
mViewportOffset.equals(viewport.getViewportOffset());
|
||||
public void setZoomFactor(float zoomFactor) {
|
||||
mZoomFactor = zoomFactor;
|
||||
}
|
||||
|
||||
/* This will set the zoom factor and re-scale page-size and viewport offset
|
||||
* accordingly. The given focus will remain at the same point on the screen
|
||||
* after scaling.
|
||||
*/
|
||||
public void scaleTo(float newZoomFactor, PointF focus) {
|
||||
float scaleFactor = newZoomFactor / mZoomFactor;
|
||||
|
||||
mPageSize = mPageSize.scale(scaleFactor);
|
||||
|
||||
PointF origin = getOrigin();
|
||||
origin.offset(focus.x, focus.y);
|
||||
origin = PointUtils.scale(origin, scaleFactor);
|
||||
origin.offset(-focus.x, -focus.y);
|
||||
setOrigin(origin);
|
||||
|
||||
mZoomFactor = newZoomFactor;
|
||||
}
|
||||
|
||||
public String toJSON() {
|
||||
|
@ -196,7 +225,8 @@ public class ViewportMetrics {
|
|||
", \"pageHeight\" : " + mPageSize.height +
|
||||
", \"offsetX\" : " + mViewportOffset.x +
|
||||
", \"offsetY\" : " + mViewportOffset.y +
|
||||
"}";
|
||||
", \"zoom\" : " + mZoomFactor +
|
||||
" }";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,11 +38,13 @@
|
|||
package org.mozilla.gecko.ui;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.FloatUtils;
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
@ -88,10 +90,8 @@ public class PanZoomController
|
|||
|
||||
private Timer mFlingTimer;
|
||||
private Axis mX, mY;
|
||||
/* The span at the first zoom event (in unzoomed page coordinates). */
|
||||
private float mInitialZoomSpan;
|
||||
/* The zoom focus at the first zoom event (in unzoomed page coordinates). */
|
||||
private PointF mInitialZoomFocus;
|
||||
/* The zoom focus at the first zoom event (in page coordinates). */
|
||||
private PointF mLastZoomFocus;
|
||||
|
||||
private enum PanZoomState {
|
||||
NOTHING, /* no touch-start events received */
|
||||
|
@ -322,8 +322,8 @@ public class PanZoomController
|
|||
|
||||
// Populates the viewport info and length in the axes.
|
||||
private void populatePositionAndLength() {
|
||||
IntSize pageSize = mController.getPageSize();
|
||||
RectF visibleRect = new RectF(mController.getViewport());
|
||||
FloatSize pageSize = mController.getPageSize();
|
||||
RectF visibleRect = mController.getViewport();
|
||||
|
||||
mX.setPageLength(pageSize.width);
|
||||
mX.viewportPos = visibleRect.left;
|
||||
|
@ -379,11 +379,6 @@ public class PanZoomController
|
|||
return 1.0f - excess / (viewportLength * SNAP_LIMIT);
|
||||
}
|
||||
|
||||
private static boolean floatsApproxEqual(float a, float b) {
|
||||
// account for floating point rounding errors
|
||||
return Math.abs(a - b) < 1e-6;
|
||||
}
|
||||
|
||||
// Physics information for one axis (X or Y).
|
||||
private static class Axis {
|
||||
public enum FlingStates {
|
||||
|
@ -411,13 +406,13 @@ public class PanZoomController
|
|||
public float viewportPos;
|
||||
private float mViewportLength;
|
||||
private int mScreenLength;
|
||||
private int mPageLength;
|
||||
private float mPageLength;
|
||||
|
||||
public FlingStates getFlingState() { return mFlingState; }
|
||||
|
||||
public void setViewportLength(float viewportLength) { mViewportLength = viewportLength; }
|
||||
public void setScreenLength(int screenLength) { mScreenLength = screenLength; }
|
||||
public void setPageLength(int pageLength) { mPageLength = pageLength; }
|
||||
public void setPageLength(float pageLength) { mPageLength = pageLength; }
|
||||
|
||||
private float getViewportEnd() { return viewportPos + mViewportLength; }
|
||||
|
||||
|
@ -458,7 +453,7 @@ public class PanZoomController
|
|||
}
|
||||
|
||||
float excess = getExcess();
|
||||
if (floatsApproxEqual(excess, 0.0f))
|
||||
if (FloatUtils.fuzzyEquals(excess, 0.0f))
|
||||
mFlingState = FlingStates.STOPPED;
|
||||
else
|
||||
mFlingState = FlingStates.WAITING_TO_SNAP;
|
||||
|
@ -483,7 +478,7 @@ public class PanZoomController
|
|||
private void scroll() {
|
||||
// If we aren't overscrolled, just apply friction.
|
||||
float excess = getExcess();
|
||||
if (floatsApproxEqual(excess, 0.0f)) {
|
||||
if (FloatUtils.fuzzyEquals(excess, 0.0f)) {
|
||||
velocity *= FRICTION;
|
||||
if (Math.abs(velocity) < 0.1f) {
|
||||
velocity = 0.0f;
|
||||
|
@ -603,47 +598,34 @@ public class PanZoomController
|
|||
*/
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
/*
|
||||
mState = PanZoomState.PINCHING;
|
||||
float newZoom = detector.getCurrentSpan() / mInitialZoomSpan;
|
||||
float newZoomFactor = mController.getZoomFactor() *
|
||||
(detector.getCurrentSpan() / detector.getPreviousSpan());
|
||||
|
||||
mController.scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(),
|
||||
mLastZoomFocus.y - detector.getFocusY()));
|
||||
mController.scaleTo(newZoomFactor, new PointF(detector.getFocusX(), detector.getFocusY()));
|
||||
|
||||
mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
|
||||
|
||||
IntSize screenSize = mController.getScreenSize();
|
||||
float x = mInitialZoomFocus.x - (detector.getFocusX() / newZoom);
|
||||
float y = mInitialZoomFocus.y - (detector.getFocusY() / newZoom);
|
||||
float width = screenSize.width / newZoom;
|
||||
float height = screenSize.height / newZoom;
|
||||
mController.setVisibleRect(x, y, width, height);
|
||||
mController.notifyLayerClientOfGeometryChange();
|
||||
populatePositionAndLength();
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
/*
|
||||
mState = PanZoomState.PINCHING;
|
||||
RectF initialZoomRect = mController.getVisibleRect();
|
||||
float initialZoom = mController.getZoomFactor();
|
||||
|
||||
mInitialZoomFocus = new PointF(initialZoomRect.left + (detector.getFocusX() / initialZoom),
|
||||
initialZoomRect.top + (detector.getFocusY() / initialZoom));
|
||||
mInitialZoomSpan = detector.getCurrentSpan() / initialZoom;
|
||||
|
||||
mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
|
||||
GeckoApp.mAppContext.hidePluginViews();
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
/*
|
||||
mState = PanZoomState.PANNING_HOLD_LOCKED;
|
||||
mX.firstTouchPos = mX.touchPos = detector.getFocusX();
|
||||
mY.firstTouchPos = mY.touchPos = detector.getFocusY();
|
||||
|
||||
GeckoApp.mAppContext.showPluginViews();
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -901,7 +901,8 @@ function Tab(aURL, aParams) {
|
|||
this.id = 0;
|
||||
this.create(aURL, aParams);
|
||||
this._viewport = { x: 0, y: 0, width: 1, height: 1, offsetX: 0, offsetY: 0,
|
||||
pageWidth: 1, pageHeight: 1 };
|
||||
pageWidth: 1, pageHeight: 1, zoom: 1.0 };
|
||||
this.viewportExcess = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
Tab.prototype = {
|
||||
|
@ -917,6 +918,7 @@ Tab.prototype = {
|
|||
this.browser.setAttribute("type", "content");
|
||||
this.browser.style.width = "980px";
|
||||
this.browser.style.height = "480px";
|
||||
this.browser.style.MozTransformOrigin = "0 0";
|
||||
this.vbox.appendChild(this.browser);
|
||||
|
||||
// Turn off clipping so we can buffer areas outside of the browser element.
|
||||
|
@ -983,11 +985,18 @@ Tab.prototype = {
|
|||
},
|
||||
|
||||
set viewport(aViewport) {
|
||||
// TODO: Zoom?
|
||||
// Transform coordinates based on zoom
|
||||
aViewport.x /= aViewport.zoom;
|
||||
aViewport.y /= aViewport.zoom;
|
||||
|
||||
// Set scroll position
|
||||
this.browser.contentWindow.scrollTo(aViewport.x, aViewport.y);
|
||||
|
||||
// If we've been asked to over-scroll, do it via the transformation
|
||||
// and store it separately to the viewport.
|
||||
let excessX = aViewport.x - this.browser.contentWindow.scrollX;
|
||||
let excessY = aViewport.y - this.browser.contentWindow.scrollY;
|
||||
|
||||
// Check if the viewport size/position has changed and set the necessary
|
||||
// attributes on the browser element.
|
||||
if (aViewport.width != this._viewport.width) {
|
||||
|
@ -1001,36 +1010,54 @@ Tab.prototype = {
|
|||
|
||||
let transformChanged = false;
|
||||
|
||||
if (aViewport.offsetX != this._viewport.offsetX) {
|
||||
if ((aViewport.offsetX != this._viewport.offsetX) ||
|
||||
(excessX != this.viewportExcess.x)) {
|
||||
this._viewport.offsetX = aViewport.offsetX;
|
||||
this.viewportExcess.x = excessX;
|
||||
transformChanged = true;
|
||||
}
|
||||
if (aViewport.offsetY != this._viewport.offsetY) {
|
||||
if ((aViewport.offsetY != this._viewport.offsetY) ||
|
||||
(excessY != this.viewportExcess.y)) {
|
||||
this._viewport.offsetY = aViewport.offsetY;
|
||||
this.viewportExcess.y = excessY;
|
||||
transformChanged = true;
|
||||
}
|
||||
if (aViewport.zoom != this._viewport.zoom) {
|
||||
this._viewport.zoom = aViewport.zoom;
|
||||
transformChanged = true;
|
||||
}
|
||||
|
||||
if (transformChanged)
|
||||
if (transformChanged) {
|
||||
this.browser.style.MozTransform =
|
||||
"translate(" + this._viewport.offsetX + "px, " +
|
||||
this._viewport.offsetY + "px)";
|
||||
"translate(" + (this._viewport.offsetX) + "px, " +
|
||||
(this._viewport.offsetY) + "px) " +
|
||||
"scale(" + this._viewport.zoom + ") " +
|
||||
"translate(" + (-excessX) + "px, " + (-excessY) + "px)";
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
get viewport() {
|
||||
// Update the viewport to current dimensions
|
||||
this._viewport.x = this.browser.contentWindow.scrollX;
|
||||
this._viewport.y = this.browser.contentWindow.scrollY;
|
||||
this._viewport.x = this.browser.contentWindow.scrollX +
|
||||
this.viewportExcess.x;
|
||||
this._viewport.y = this.browser.contentWindow.scrollY +
|
||||
this.viewportExcess.y;
|
||||
|
||||
let doc = this.browser.contentDocument.documentElement;
|
||||
let pageWidth = this._viewport.width;
|
||||
let pageHeight = this._viewport.height;
|
||||
if (doc != null) {
|
||||
this._viewport.pageWidth = doc.scrollWidth;
|
||||
this._viewport.pageHeight = doc.scrollHeight;
|
||||
} else {
|
||||
this._viewport.pageWidth = this._viewport.width;
|
||||
this._viewport.pageHeight = this._viewport.height;
|
||||
pageWidth = Math.max(pageWidth, doc.scrollWidth);
|
||||
pageHeight = Math.max(pageHeight, doc.scrollHeight);
|
||||
}
|
||||
|
||||
// Transform coordinates based on zoom
|
||||
this._viewport.x *= this._viewport.zoom;
|
||||
this._viewport.y *= this._viewport.zoom;
|
||||
this._viewport.pageWidth = pageWidth * this._viewport.zoom;
|
||||
this._viewport.pageHeight = pageHeight * this._viewport.zoom;
|
||||
|
||||
return this._viewport;
|
||||
},
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче