mobile/android/base/gfx/Layer.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial