Wed, 31 Dec 2014 06:09:35 +0100
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 |