package org.emdev.ui.gl; import android.graphics.PointF; import android.graphics.RectF; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; public class GLClipHelper { private int count = 0; private final ClipRegion[] regions = new ClipRegion[256]; final GLCanvasImpl canvas; GLClipHelper(final GLCanvasImpl canvas) { this.canvas = canvas; } void setClipRect(final RectF bounds) { setClipRect(bounds.left, bounds.top, bounds.width(), bounds.height()); } void setClipRect(final float left, final float top, final float width, final float height) { final GL11 gl = canvas.mGL; push(gl, new ClipRect(left, top, width, height)); drawClipRegions(gl); } void setClipPath(final PointF... path) { final GL11 gl = canvas.mGL; push(gl, new ClipPath(path)); drawClipRegions(gl); } void push(final GL11 gl, final ClipRegion clipRect) { if (count == 0) { gl.glEnable(GL10.GL_STENCIL_TEST); } regions[count++] = clipRect; } void drawClipRegions(final GL11 gl) { gl.glClear(GL10.GL_STENCIL_BUFFER_BIT); gl.glColorMask(false, false, false, false); gl.glStencilFunc(GL10.GL_ALWAYS, 1, ~0); gl.glStencilOp(GL10.GL_INCR, GL10.GL_INCR, GL10.GL_INCR); for (int i = 0; i < count; i++) { regions[i].draw(canvas); } gl.glColorMask(true, true, true, true); gl.glStencilFunc(GL10.GL_EQUAL, count, ~0); gl.glStencilOp(GL10.GL_KEEP, GL10.GL_KEEP, GL10.GL_KEEP); } void clearClipRect() { if (count <= 0) { return; } final GL11 gl = canvas.mGL; count--; regions[count] = null; if (count > 0) { drawClipRegions(gl); } else { gl.glDisable(GL10.GL_STENCIL_TEST); } } static interface ClipRegion { void draw(final GLCanvas canvas); } static class ClipRect implements ClipRegion { final float left, top, width, height; ClipRect(final float left, final float top, final float width, final float height) { this.left = left; this.top = top; this.width = width; this.height = height; } @Override public void draw(final GLCanvas canvas) { canvas.fillRect(left, top, width, height, 1); } } static class ClipPath implements ClipRegion { final PointF[] path; ClipPath(final PointF... path) { this.path = path; } @Override public void draw(final GLCanvas canvas) { canvas.fillPoly(1, path); } } }