mobile/android/base/gfx/Layer.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko.gfx;
michael@0 7
michael@0 8 import org.mozilla.gecko.util.FloatUtils;
michael@0 9
michael@0 10 import android.graphics.PointF;
michael@0 11 import android.graphics.Rect;
michael@0 12 import android.graphics.RectF;
michael@0 13
michael@0 14 import java.nio.FloatBuffer;
michael@0 15 import java.util.concurrent.locks.ReentrantLock;
michael@0 16
michael@0 17 public abstract class Layer {
michael@0 18 private final ReentrantLock mTransactionLock;
michael@0 19 private boolean mInTransaction;
michael@0 20 private Rect mNewPosition;
michael@0 21 private float mNewResolution;
michael@0 22
michael@0 23 protected Rect mPosition;
michael@0 24 protected float mResolution;
michael@0 25
michael@0 26 public Layer() {
michael@0 27 this(null);
michael@0 28 }
michael@0 29
michael@0 30 public Layer(IntSize size) {
michael@0 31 mTransactionLock = new ReentrantLock();
michael@0 32 if (size == null) {
michael@0 33 mPosition = new Rect();
michael@0 34 } else {
michael@0 35 mPosition = new Rect(0, 0, size.width, size.height);
michael@0 36 }
michael@0 37 mResolution = 1.0f;
michael@0 38 }
michael@0 39
michael@0 40 /**
michael@0 41 * Updates the layer. This returns false if there is still work to be done
michael@0 42 * after this update.
michael@0 43 */
michael@0 44 public final boolean update(RenderContext context) {
michael@0 45 if (mTransactionLock.isHeldByCurrentThread()) {
michael@0 46 throw new RuntimeException("draw() called while transaction lock held by this " +
michael@0 47 "thread?!");
michael@0 48 }
michael@0 49
michael@0 50 if (mTransactionLock.tryLock()) {
michael@0 51 try {
michael@0 52 performUpdates(context);
michael@0 53 return true;
michael@0 54 } finally {
michael@0 55 mTransactionLock.unlock();
michael@0 56 }
michael@0 57 }
michael@0 58
michael@0 59 return false;
michael@0 60 }
michael@0 61
michael@0 62 /** Subclasses override this function to draw the layer. */
michael@0 63 public abstract void draw(RenderContext context);
michael@0 64
michael@0 65 /** Given the intrinsic size of the layer, returns the pixel boundaries of the layer rect. */
michael@0 66 protected RectF getBounds(RenderContext context) {
michael@0 67 return RectUtils.scale(new RectF(mPosition), context.zoomFactor / mResolution);
michael@0 68 }
michael@0 69
michael@0 70 /**
michael@0 71 * Call this before modifying the layer. Note that, for TileLayers, "modifying the layer"
michael@0 72 * includes altering the underlying CairoImage in any way. Thus you must call this function
michael@0 73 * before modifying the byte buffer associated with this layer.
michael@0 74 *
michael@0 75 * This function may block, so you should never call this on the main UI thread.
michael@0 76 */
michael@0 77 public void beginTransaction() {
michael@0 78 if (mTransactionLock.isHeldByCurrentThread())
michael@0 79 throw new RuntimeException("Nested transactions are not supported");
michael@0 80 mTransactionLock.lock();
michael@0 81 mInTransaction = true;
michael@0 82 mNewResolution = mResolution;
michael@0 83 }
michael@0 84
michael@0 85 /** Call this when you're done modifying the layer. */
michael@0 86 public void endTransaction() {
michael@0 87 if (!mInTransaction)
michael@0 88 throw new RuntimeException("endTransaction() called outside a transaction");
michael@0 89 mInTransaction = false;
michael@0 90 mTransactionLock.unlock();
michael@0 91 }
michael@0 92
michael@0 93 /** Returns true if the layer is currently in a transaction and false otherwise. */
michael@0 94 protected boolean inTransaction() {
michael@0 95 return mInTransaction;
michael@0 96 }
michael@0 97
michael@0 98 /** Returns the current layer position. */
michael@0 99 public Rect getPosition() {
michael@0 100 return mPosition;
michael@0 101 }
michael@0 102
michael@0 103 /** Sets the position. Only valid inside a transaction. */
michael@0 104 public void setPosition(Rect newPosition) {
michael@0 105 if (!mInTransaction)
michael@0 106 throw new RuntimeException("setPosition() is only valid inside a transaction");
michael@0 107 mNewPosition = newPosition;
michael@0 108 }
michael@0 109
michael@0 110 /** Returns the current layer's resolution. */
michael@0 111 public float getResolution() {
michael@0 112 return mResolution;
michael@0 113 }
michael@0 114
michael@0 115 /**
michael@0 116 * Sets the layer resolution. This value is used to determine how many pixels per
michael@0 117 * device pixel this layer was rendered at. This will be reflected by scaling by
michael@0 118 * the reciprocal of the resolution in the layer's transform() function.
michael@0 119 * Only valid inside a transaction. */
michael@0 120 public void setResolution(float newResolution) {
michael@0 121 if (!mInTransaction)
michael@0 122 throw new RuntimeException("setResolution() is only valid inside a transaction");
michael@0 123 mNewResolution = newResolution;
michael@0 124 }
michael@0 125
michael@0 126 /**
michael@0 127 * Subclasses may override this method to perform custom layer updates. This will be called
michael@0 128 * with the transaction lock held. Subclass implementations of this method must call the
michael@0 129 * superclass implementation. Returns false if there is still work to be done after this
michael@0 130 * update is complete.
michael@0 131 */
michael@0 132 protected void performUpdates(RenderContext context) {
michael@0 133 if (mNewPosition != null) {
michael@0 134 mPosition = mNewPosition;
michael@0 135 mNewPosition = null;
michael@0 136 }
michael@0 137 if (mNewResolution != 0.0f) {
michael@0 138 mResolution = mNewResolution;
michael@0 139 mNewResolution = 0.0f;
michael@0 140 }
michael@0 141 }
michael@0 142
michael@0 143 /**
michael@0 144 * This function fills in the provided <tt>dest</tt> array with values to render a texture.
michael@0 145 * The array is filled with 4 sets of {x, y, z, texture_x, texture_y} values (so 20 values
michael@0 146 * in total) corresponding to the corners of the rect.
michael@0 147 */
michael@0 148 protected final void fillRectCoordBuffer(float[] dest, RectF rect, float viewWidth, float viewHeight,
michael@0 149 Rect cropRect, float texWidth, float texHeight) {
michael@0 150 //x, y, z, texture_x, texture_y
michael@0 151 dest[0] = rect.left / viewWidth;
michael@0 152 dest[1] = rect.bottom / viewHeight;
michael@0 153 dest[2] = 0;
michael@0 154 dest[3] = cropRect.left / texWidth;
michael@0 155 dest[4] = cropRect.top / texHeight;
michael@0 156
michael@0 157 dest[5] = rect.left / viewWidth;
michael@0 158 dest[6] = rect.top / viewHeight;
michael@0 159 dest[7] = 0;
michael@0 160 dest[8] = cropRect.left / texWidth;
michael@0 161 dest[9] = cropRect.bottom / texHeight;
michael@0 162
michael@0 163 dest[10] = rect.right / viewWidth;
michael@0 164 dest[11] = rect.bottom / viewHeight;
michael@0 165 dest[12] = 0;
michael@0 166 dest[13] = cropRect.right / texWidth;
michael@0 167 dest[14] = cropRect.top / texHeight;
michael@0 168
michael@0 169 dest[15] = rect.right / viewWidth;
michael@0 170 dest[16] = rect.top / viewHeight;
michael@0 171 dest[17] = 0;
michael@0 172 dest[18] = cropRect.right / texWidth;
michael@0 173 dest[19] = cropRect.bottom / texHeight;
michael@0 174 }
michael@0 175
michael@0 176 public static class RenderContext {
michael@0 177 public final RectF viewport;
michael@0 178 public final RectF pageRect;
michael@0 179 public final float zoomFactor;
michael@0 180 public final PointF offset;
michael@0 181 public final int positionHandle;
michael@0 182 public final int textureHandle;
michael@0 183 public final FloatBuffer coordBuffer;
michael@0 184
michael@0 185 public RenderContext(RectF aViewport, RectF aPageRect, float aZoomFactor, PointF aOffset,
michael@0 186 int aPositionHandle, int aTextureHandle, FloatBuffer aCoordBuffer) {
michael@0 187 viewport = aViewport;
michael@0 188 pageRect = aPageRect;
michael@0 189 zoomFactor = aZoomFactor;
michael@0 190 offset = aOffset;
michael@0 191 positionHandle = aPositionHandle;
michael@0 192 textureHandle = aTextureHandle;
michael@0 193 coordBuffer = aCoordBuffer;
michael@0 194 }
michael@0 195
michael@0 196 public boolean fuzzyEquals(RenderContext other) {
michael@0 197 if (other == null) {
michael@0 198 return false;
michael@0 199 }
michael@0 200 return RectUtils.fuzzyEquals(viewport, other.viewport)
michael@0 201 && RectUtils.fuzzyEquals(pageRect, other.pageRect)
michael@0 202 && FloatUtils.fuzzyEquals(zoomFactor, other.zoomFactor)
michael@0 203 && FloatUtils.fuzzyEquals(offset, other.offset);
michael@0 204 }
michael@0 205 }
michael@0 206 }
michael@0 207

mercurial