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 android
.graphics
.RectF
;
9 import android
.opengl
.GLES20
;
11 import java
.nio
.FloatBuffer
;
14 * Encapsulates the logic needed to draw a nine-patch bitmap using OpenGL ES.
16 * For more information on nine-patch bitmaps, see the following document:
17 * http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
19 public class NinePatchTileLayer
extends TileLayer
{
20 private static final int PATCH_SIZE
= 16;
21 private static final int TEXTURE_SIZE
= 64;
23 public NinePatchTileLayer(CairoImage image
) {
24 super(image
, PaintMode
.NORMAL
);
28 public void draw(RenderContext context
) {
32 GLES20
.glBlendFunc(GLES20
.GL_SRC_ALPHA
, GLES20
.GL_ONE_MINUS_SRC_ALPHA
);
33 GLES20
.glEnable(GLES20
.GL_BLEND
);
35 GLES20
.glBindTexture(GLES20
.GL_TEXTURE_2D
, getTextureID());
39 private void drawPatches(RenderContext context
) {
41 * We divide the nine-patch bitmap up as follows:
52 // page is the rect of the "missing" center spot in the picture above
53 RectF page
= context
.pageRect
;
55 drawPatch(context
, 0, PATCH_SIZE
* 3, /* 0 */
56 page
.left
- PATCH_SIZE
, page
.top
- PATCH_SIZE
, PATCH_SIZE
, PATCH_SIZE
);
57 drawPatch(context
, PATCH_SIZE
, PATCH_SIZE
* 3, /* 1 */
58 page
.left
, page
.top
- PATCH_SIZE
, page
.width(), PATCH_SIZE
);
59 drawPatch(context
, PATCH_SIZE
* 2, PATCH_SIZE
* 3, /* 2 */
60 page
.right
, page
.top
- PATCH_SIZE
, PATCH_SIZE
, PATCH_SIZE
);
61 drawPatch(context
, 0, PATCH_SIZE
* 2, /* 3 */
62 page
.left
- PATCH_SIZE
, page
.top
, PATCH_SIZE
, page
.height());
63 drawPatch(context
, PATCH_SIZE
* 2, PATCH_SIZE
* 2, /* 4 */
64 page
.right
, page
.top
, PATCH_SIZE
, page
.height());
65 drawPatch(context
, 0, PATCH_SIZE
, /* 5 */
66 page
.left
- PATCH_SIZE
, page
.bottom
, PATCH_SIZE
, PATCH_SIZE
);
67 drawPatch(context
, PATCH_SIZE
, PATCH_SIZE
, /* 6 */
68 page
.left
, page
.bottom
, page
.width(), PATCH_SIZE
);
69 drawPatch(context
, PATCH_SIZE
* 2, PATCH_SIZE
, /* 7 */
70 page
.right
, page
.bottom
, PATCH_SIZE
, PATCH_SIZE
);
73 private void drawPatch(RenderContext context
, int textureX
, int textureY
,
74 float tileX
, float tileY
, float tileWidth
, float tileHeight
) {
75 RectF viewport
= context
.viewport
;
76 float viewportHeight
= viewport
.height();
77 float drawX
= tileX
- viewport
.left
;
78 float drawY
= viewportHeight
- (tileY
+ tileHeight
- viewport
.top
);
81 //x, y, z, texture_x, texture_y
82 drawX
/viewport
.width(), drawY
/viewport
.height(), 0,
83 textureX
/(float)TEXTURE_SIZE
, textureY
/(float)TEXTURE_SIZE
,
85 drawX
/viewport
.width(), (drawY
+tileHeight
)/viewport
.height(), 0,
86 textureX
/(float)TEXTURE_SIZE
, (textureY
+PATCH_SIZE
)/(float)TEXTURE_SIZE
,
88 (drawX
+tileWidth
)/viewport
.width(), drawY
/viewport
.height(), 0,
89 (textureX
+PATCH_SIZE
)/(float)TEXTURE_SIZE
, textureY
/(float)TEXTURE_SIZE
,
91 (drawX
+tileWidth
)/viewport
.width(), (drawY
+tileHeight
)/viewport
.height(), 0,
92 (textureX
+PATCH_SIZE
)/(float)TEXTURE_SIZE
, (textureY
+PATCH_SIZE
)/(float)TEXTURE_SIZE
96 // Get the buffer and handles from the context
97 FloatBuffer coordBuffer
= context
.coordBuffer
;
98 int positionHandle
= context
.positionHandle
;
99 int textureHandle
= context
.textureHandle
;
101 // Make sure we are at position zero in the buffer in case other draw methods did not clean
102 // up after themselves
103 coordBuffer
.position(0);
104 coordBuffer
.put(coords
);
106 // Unbind any the current array buffer so we can use client side buffers
107 GLES20
.glBindBuffer(GLES20
.GL_ARRAY_BUFFER
, 0);
109 // Vertex coordinates are x,y,z starting at position 0 into the buffer.
110 coordBuffer
.position(0);
111 GLES20
.glVertexAttribPointer(positionHandle
, 3, GLES20
.GL_FLOAT
, false, 20, coordBuffer
);
113 // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
114 coordBuffer
.position(3);
115 GLES20
.glVertexAttribPointer(textureHandle
, 2, GLES20
.GL_FLOAT
, false, 20, coordBuffer
);
117 GLES20
.glTexParameterf(GLES20
.GL_TEXTURE_2D
, GLES20
.GL_TEXTURE_WRAP_S
,
118 GLES20
.GL_CLAMP_TO_EDGE
);
119 GLES20
.glTexParameterf(GLES20
.GL_TEXTURE_2D
, GLES20
.GL_TEXTURE_WRAP_T
,
120 GLES20
.GL_CLAMP_TO_EDGE
);
122 // Use bilinear filtering for both magnification and minimization of the texture. This
123 // applies only to the shadow layer so we do not incur a high overhead.
124 GLES20
.glTexParameteri(GLES20
.GL_TEXTURE_2D
, GLES20
.GL_TEXTURE_MAG_FILTER
,
126 GLES20
.glTexParameteri(GLES20
.GL_TEXTURE_2D
, GLES20
.GL_TEXTURE_MIN_FILTER
,
129 GLES20
.glDrawArrays(GLES20
.GL_TRIANGLE_STRIP
, 0, 4);