mobile/android/base/gfx/SingleTileLayer.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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 android.graphics.Rect;
michael@0 9 import android.graphics.RectF;
michael@0 10 import android.graphics.Region;
michael@0 11 import android.graphics.RegionIterator;
michael@0 12 import android.opengl.GLES20;
michael@0 13
michael@0 14 import java.nio.FloatBuffer;
michael@0 15
michael@0 16 /**
michael@0 17 * Encapsulates the logic needed to draw a single textured tile.
michael@0 18 *
michael@0 19 * TODO: Repeating textures really should be their own type of layer.
michael@0 20 */
michael@0 21 public class SingleTileLayer extends TileLayer {
michael@0 22 private static final String LOGTAG = "GeckoSingleTileLayer";
michael@0 23
michael@0 24 private Rect mMask;
michael@0 25
michael@0 26 // To avoid excessive GC, declare some objects here that would otherwise
michael@0 27 // be created and destroyed frequently during draw().
michael@0 28 private final RectF mBounds;
michael@0 29 private final RectF mTextureBounds;
michael@0 30 private final RectF mViewport;
michael@0 31 private final Rect mIntBounds;
michael@0 32 private final Rect mSubRect;
michael@0 33 private final RectF mSubRectF;
michael@0 34 private final Region mMaskedBounds;
michael@0 35 private final Rect mCropRect;
michael@0 36 private final RectF mObjRectF;
michael@0 37 private final float[] mCoords;
michael@0 38
michael@0 39 public SingleTileLayer(CairoImage image) {
michael@0 40 this(false, image);
michael@0 41 }
michael@0 42
michael@0 43 public SingleTileLayer(boolean repeat, CairoImage image) {
michael@0 44 this(image, repeat ? TileLayer.PaintMode.REPEAT : TileLayer.PaintMode.NORMAL);
michael@0 45 }
michael@0 46
michael@0 47 public SingleTileLayer(CairoImage image, TileLayer.PaintMode paintMode) {
michael@0 48 super(image, paintMode);
michael@0 49
michael@0 50 mBounds = new RectF();
michael@0 51 mTextureBounds = new RectF();
michael@0 52 mViewport = new RectF();
michael@0 53 mIntBounds = new Rect();
michael@0 54 mSubRect = new Rect();
michael@0 55 mSubRectF = new RectF();
michael@0 56 mMaskedBounds = new Region();
michael@0 57 mCropRect = new Rect();
michael@0 58 mObjRectF = new RectF();
michael@0 59 mCoords = new float[20];
michael@0 60 }
michael@0 61
michael@0 62 /**
michael@0 63 * Set an area to mask out when rendering.
michael@0 64 */
michael@0 65 public void setMask(Rect aMaskRect) {
michael@0 66 mMask = aMaskRect;
michael@0 67 }
michael@0 68
michael@0 69 @Override
michael@0 70 public void draw(RenderContext context) {
michael@0 71 // mTextureIDs may be null here during startup if Layer.java's draw method
michael@0 72 // failed to acquire the transaction lock and call performUpdates.
michael@0 73 if (!initialized())
michael@0 74 return;
michael@0 75
michael@0 76 mViewport.set(context.viewport);
michael@0 77
michael@0 78 if (repeats()) {
michael@0 79 // If we're repeating, we want to adjust the texture bounds so that
michael@0 80 // the texture repeats the correct number of times when drawn at
michael@0 81 // the size of the viewport.
michael@0 82 mBounds.set(getBounds(context));
michael@0 83 mTextureBounds.set(0.0f, 0.0f, mBounds.width(), mBounds.height());
michael@0 84 mBounds.set(0.0f, 0.0f, mViewport.width(), mViewport.height());
michael@0 85 } else if (stretches()) {
michael@0 86 // If we're stretching, we just want the bounds and texture bounds
michael@0 87 // to fit to the page.
michael@0 88 mBounds.set(context.pageRect);
michael@0 89 mTextureBounds.set(mBounds);
michael@0 90 } else {
michael@0 91 mBounds.set(getBounds(context));
michael@0 92 mTextureBounds.set(mBounds);
michael@0 93 }
michael@0 94
michael@0 95 mBounds.roundOut(mIntBounds);
michael@0 96 mMaskedBounds.set(mIntBounds);
michael@0 97 if (mMask != null) {
michael@0 98 mMaskedBounds.op(mMask, Region.Op.DIFFERENCE);
michael@0 99 if (mMaskedBounds.isEmpty())
michael@0 100 return;
michael@0 101 }
michael@0 102
michael@0 103 // XXX Possible optimisation here, form this array so we can draw it in
michael@0 104 // a single call.
michael@0 105 RegionIterator i = new RegionIterator(mMaskedBounds);
michael@0 106 while (i.next(mSubRect)) {
michael@0 107 // Compensate for rounding errors at the edge of the tile caused by
michael@0 108 // the roundOut above
michael@0 109 mSubRectF.set(Math.max(mBounds.left, (float)mSubRect.left),
michael@0 110 Math.max(mBounds.top, (float)mSubRect.top),
michael@0 111 Math.min(mBounds.right, (float)mSubRect.right),
michael@0 112 Math.min(mBounds.bottom, (float)mSubRect.bottom));
michael@0 113
michael@0 114 // This is the left/top/right/bottom of the rect, relative to the
michael@0 115 // bottom-left of the layer, to use for texture coordinates.
michael@0 116 mCropRect.set(Math.round(mSubRectF.left - mBounds.left),
michael@0 117 Math.round(mBounds.bottom - mSubRectF.top),
michael@0 118 Math.round(mSubRectF.right - mBounds.left),
michael@0 119 Math.round(mBounds.bottom - mSubRectF.bottom));
michael@0 120
michael@0 121 mObjRectF.set(mSubRectF.left - mViewport.left,
michael@0 122 mViewport.bottom - mSubRectF.bottom,
michael@0 123 mSubRectF.right - mViewport.left,
michael@0 124 mViewport.bottom - mSubRectF.top);
michael@0 125
michael@0 126 fillRectCoordBuffer(mCoords, mObjRectF, mViewport.width(), mViewport.height(),
michael@0 127 mCropRect, mTextureBounds.width(), mTextureBounds.height());
michael@0 128
michael@0 129 FloatBuffer coordBuffer = context.coordBuffer;
michael@0 130 int positionHandle = context.positionHandle;
michael@0 131 int textureHandle = context.textureHandle;
michael@0 132
michael@0 133 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
michael@0 134 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID());
michael@0 135
michael@0 136 // Make sure we are at position zero in the buffer
michael@0 137 coordBuffer.position(0);
michael@0 138 coordBuffer.put(mCoords);
michael@0 139
michael@0 140 // Unbind any the current array buffer so we can use client side buffers
michael@0 141 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
michael@0 142
michael@0 143 // Vertex coordinates are x,y,z starting at position 0 into the buffer.
michael@0 144 coordBuffer.position(0);
michael@0 145 GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
michael@0 146
michael@0 147 // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
michael@0 148 coordBuffer.position(3);
michael@0 149 GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer);
michael@0 150 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
michael@0 151 }
michael@0 152 }
michael@0 153 }

mercurial